convertible-cli 0.4.0__tar.gz → 0.5.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 (122) hide show
  1. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/CHANGELOG.md +7 -0
  2. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/PKG-INFO +32 -3
  3. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/README.md +31 -2
  4. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/__init__.py +19 -0
  5. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/drive.py +5 -2
  6. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/explain/catalog.py +10 -5
  7. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/pyproject.toml +1 -1
  8. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_cli.py +23 -1
  9. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/uv.lock +1 -1
  10. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/agent-config/SKILL.md +0 -0
  11. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  12. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
  13. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  14. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  15. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/SKILL.md +0 -0
  16. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  17. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  18. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  19. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  20. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  21. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/SKILL.md +0 -0
  22. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  23. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  24. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  25. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  26. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
  27. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  28. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  29. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  30. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  31. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  32. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/run-tests/SKILL.md +0 -0
  33. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  34. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  35. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  36. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  37. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  38. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/think/SKILL.md +0 -0
  39. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/think/scripts/think.sh +0 -0
  40. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/version-bump/SKILL.md +0 -0
  41. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  42. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.claude/skills.local.yaml.example +0 -0
  43. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/current +0 -0
  44. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/current_plan +0 -0
  45. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/frames/convertible-gains-an-extensibility-layer-like-clau.json +0 -0
  46. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/frames/convertible-v0-ships-point-it-at-a-repo-task-and-i.json +0 -0
  47. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/plans/convertible-gains-an-extensibility-layer-like-clau.json +0 -0
  48. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.devague/plans/convertible-v0-ships-point-it-at-a-repo-task-and-i.json +0 -0
  49. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.flake8 +0 -0
  50. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.github/workflows/publish.yml +0 -0
  51. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.github/workflows/tests.yml +0 -0
  52. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.gitignore +0 -0
  53. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/.markdownlint-cli2.yaml +0 -0
  54. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/CLAUDE.md +0 -0
  55. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/LICENSE +0 -0
  56. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/__init__.py +0 -0
  57. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/__main__.py +0 -0
  58. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/artifact.py +0 -0
  59. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_banner-big.txt +0 -0
  60. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_banner.py +0 -0
  61. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_banner.txt +0 -0
  62. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/__init__.py +0 -0
  63. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/cli.py +0 -0
  64. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/commands.py +0 -0
  65. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/doctor.py +0 -0
  66. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/explain.py +0 -0
  67. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/hooks.py +0 -0
  68. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/learn.py +0 -0
  69. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/overview.py +0 -0
  70. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/session.py +0 -0
  71. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/wheels.py +0 -0
  72. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_commands/whoami.py +0 -0
  73. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_errors.py +0 -0
  74. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/cli/_output.py +0 -0
  75. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/commands.py +0 -0
  76. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/config.py +0 -0
  77. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/configdir.py +0 -0
  78. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/contract.py +0 -0
  79. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/engine.py +0 -0
  80. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/engines/__init__.py +0 -0
  81. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/engines/mock.py +0 -0
  82. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/engines/vllm_openai.py +0 -0
  83. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/explain/__init__.py +0 -0
  84. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/handoff.py +0 -0
  85. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/hooks.py +0 -0
  86. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/loop.py +0 -0
  87. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/registry.py +0 -0
  88. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/convertible/tools.py +0 -0
  89. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/culture.yaml +0 -0
  90. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/docs/plans/2026-05-26-convertible-v0-ships-point-it-at-a-repo-task-and-i.md +0 -0
  91. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/docs/plans/2026-05-27-convertible-gains-an-extensibility-layer-like-clau.md +0 -0
  92. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/docs/skill-sources.md +0 -0
  93. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/docs/specs/2026-05-26-convertible-v0-ships-point-it-at-a-repo-task-and-i.md +0 -0
  94. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/docs/specs/2026-05-27-convertible-gains-an-extensibility-layer-like-clau.md +0 -0
  95. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/sonar-project.properties +0 -0
  96. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/__init__.py +0 -0
  97. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_artifact.py +0 -0
  98. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_banner.py +0 -0
  99. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_boundary.py +0 -0
  100. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_cli_introspection.py +0 -0
  101. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_commands.py +0 -0
  102. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_commands_cli.py +0 -0
  103. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_config.py +0 -0
  104. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_configdir.py +0 -0
  105. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_contract.py +0 -0
  106. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_drive.py +0 -0
  107. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_e2e_extensibility.py +0 -0
  108. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_e2e_mock.py +0 -0
  109. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_engine.py +0 -0
  110. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_handoff.py +0 -0
  111. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_hooks.py +0 -0
  112. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_hooks_cli.py +0 -0
  113. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_loop.py +0 -0
  114. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_mock_engine.py +0 -0
  115. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_registry.py +0 -0
  116. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_review_fixes.py +0 -0
  117. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_session.py +0 -0
  118. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_tools.py +0 -0
  119. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_vllm_live.py +0 -0
  120. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_vllm_openai.py +0 -0
  121. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_wheels.py +0 -0
  122. {convertible_cli-0.4.0 → convertible_cli-0.5.0}/tests/test_zero_deps.py +0 -0
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/). This project
6
6
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] - 2026-05-27
9
+
10
+ ### Changed
11
+
12
+ - Bare `convertible` (no subcommand) now opens the interactive harness (the `session` palette) when run at a terminal — the natural "get in and drive" gesture. Piped, redirected, or otherwise non-interactive, it still prints usage, preserving the discoverable surface for scripts and agents. `-h/--help` is unaffected.
13
+ - Reframed `convertible drive` help and `explain` text to lead with the goal/instruction ("drive toward a goal") rather than "run a repo task"; the repo is the target, not the headline. No behavior change.
14
+
8
15
  ## [0.4.0] - 2026-05-27
9
16
 
10
17
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convertible-cli
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Convertible CLI is a swappable coder-agent harness that turns different models into repo workers behind one shared task contract.
5
5
  Project-URL: Homepage, https://github.com/agentculture/convertible
6
6
  Project-URL: Issues, https://github.com/agentculture/convertible/issues
@@ -17,6 +17,27 @@ Description-Content-Type: text/markdown
17
17
 
18
18
  # convertible
19
19
 
20
+ ```text
21
+ ,"^,::,:::::I::::::^
22
+ ^!'` `"^,. ::`
23
+ `,;;i;,,' .!^'`",. "<," " ;,^
24
+ ^ '"^";"^```,":::','"'^`"."'.,:^,i::,"".
25
+ .I. ' I-l '",I;!ii,I.,,l;;IlIl:i!:::::,,,^^;",,'
26
+ '^ ""::``':. .`";,"```"^.. '^^'":,''.
27
+ ::,`;!"..^..'^"^ .' .."" ..`"^ ..`"`'"".
28
+ ;;l!i:' ^ '^"`. `"`.. ',^.. `` '^
29
+ :i>I!lII". .' .''^` '`^' .`". ^. :;lI.
30
+ ",l!`;"':l;,,`. .' '",'. ^...'^`'"...^l'":;Ii!!l:!';.
31
+ ^''^., '`^^`:l;"^"',!~ .^^^,""..'`^. .^l,I''^.:l!;;;i>|+,!IlI::^
32
+ `;. :>i":` "`, ',^^" "; I.'. :::"^:;iil;'":^; '"
33
+ '^"'"IlI,.:,::;:' .`;"!l:``,,"``',,,^,,:ll!,,l^
34
+ ":^:,I^:"!;:: :I>l:::"`""::,:I>!<i^ " ;.
35
+ ",;"Il;i^: ',":;"`'`'^, ><[il```'
36
+ " ;;I"l:^.^;^''lI" :^::",:,'
37
+ ,`:;,I.^ ''
38
+ `. " "
39
+ ```
40
+
20
41
  > Convertible CLI is a swappable coder-agent harness that turns different models
21
42
  > into repo workers behind one shared task contract.
22
43
  >
@@ -106,10 +127,13 @@ engine, so it binds equally to `mock`, `vllm-openai`, and any future wheel.
106
127
  uv sync
107
128
  uv run pytest -n auto # full suite, no network needed
108
129
 
130
+ # Open the interactive harness (the session palette) at a terminal:
131
+ uv run convertible
132
+
109
133
  # Discover the engines installed in this environment:
110
134
  uv run convertible wheels list
111
135
 
112
- # Drive a task with the deterministic mock engine (no model, no network):
136
+ # Drive toward a goal with the deterministic mock engine (no model, no network):
113
137
  uv run convertible drive "add a CONTRIBUTING.md stub" --repo . --engine mock --no-pr
114
138
  ```
115
139
 
@@ -297,6 +321,11 @@ loop, hooks, and artifact — no parallel code path):
297
321
  uv run convertible session --repo /path/to/repo --engine vllm-openai
298
322
  ```
299
323
 
324
+ Running `convertible` with no arguments **at a terminal** opens this same palette
325
+ (with the default engine and repo) — the natural "get in and drive" gesture.
326
+ Piped, redirected, or otherwise non-interactive, bare `convertible` prints usage
327
+ instead, so scripts and agents keep a discoverable surface.
328
+
300
329
  The session loops until the user enters `q`, `quit`, or an empty line. Any
301
330
  driver flags accepted by `drive` (`--engine`, `--no-pr`, `--base-url`, etc.)
302
331
  are also accepted by `session`.
@@ -333,7 +362,7 @@ rely on a non-existent flag.
333
362
 
334
363
  | Verb | What it does |
335
364
  |------|--------------|
336
- | `drive <instruction>` | Run a repo task through a coder engine; write the artifact; hand off. |
365
+ | `drive <goal>` | Drive toward a goal/instruction: work autonomously through a coder engine; write the artifact; hand off. |
337
366
  | `drive --command <name> [args…]` | Expand a saved command template and drive it. |
338
367
  | `commands list` | List discovered command templates for a repo. |
339
368
  | `commands overview` | Describe the commands surface. |
@@ -1,5 +1,26 @@
1
1
  # convertible
2
2
 
3
+ ```text
4
+ ,"^,::,:::::I::::::^
5
+ ^!'` `"^,. ::`
6
+ `,;;i;,,' .!^'`",. "<," " ;,^
7
+ ^ '"^";"^```,":::','"'^`"."'.,:^,i::,"".
8
+ .I. ' I-l '",I;!ii,I.,,l;;IlIl:i!:::::,,,^^;",,'
9
+ '^ ""::``':. .`";,"```"^.. '^^'":,''.
10
+ ::,`;!"..^..'^"^ .' .."" ..`"^ ..`"`'"".
11
+ ;;l!i:' ^ '^"`. `"`.. ',^.. `` '^
12
+ :i>I!lII". .' .''^` '`^' .`". ^. :;lI.
13
+ ",l!`;"':l;,,`. .' '",'. ^...'^`'"...^l'":;Ii!!l:!';.
14
+ ^''^., '`^^`:l;"^"',!~ .^^^,""..'`^. .^l,I''^.:l!;;;i>|+,!IlI::^
15
+ `;. :>i":` "`, ',^^" "; I.'. :::"^:;iil;'":^; '"
16
+ '^"'"IlI,.:,::;:' .`;"!l:``,,"``',,,^,,:ll!,,l^
17
+ ":^:,I^:"!;:: :I>l:::"`""::,:I>!<i^ " ;.
18
+ ",;"Il;i^: ',":;"`'`'^, ><[il```'
19
+ " ;;I"l:^.^;^''lI" :^::",:,'
20
+ ,`:;,I.^ ''
21
+ `. " "
22
+ ```
23
+
3
24
  > Convertible CLI is a swappable coder-agent harness that turns different models
4
25
  > into repo workers behind one shared task contract.
5
26
  >
@@ -89,10 +110,13 @@ engine, so it binds equally to `mock`, `vllm-openai`, and any future wheel.
89
110
  uv sync
90
111
  uv run pytest -n auto # full suite, no network needed
91
112
 
113
+ # Open the interactive harness (the session palette) at a terminal:
114
+ uv run convertible
115
+
92
116
  # Discover the engines installed in this environment:
93
117
  uv run convertible wheels list
94
118
 
95
- # Drive a task with the deterministic mock engine (no model, no network):
119
+ # Drive toward a goal with the deterministic mock engine (no model, no network):
96
120
  uv run convertible drive "add a CONTRIBUTING.md stub" --repo . --engine mock --no-pr
97
121
  ```
98
122
 
@@ -280,6 +304,11 @@ loop, hooks, and artifact — no parallel code path):
280
304
  uv run convertible session --repo /path/to/repo --engine vllm-openai
281
305
  ```
282
306
 
307
+ Running `convertible` with no arguments **at a terminal** opens this same palette
308
+ (with the default engine and repo) — the natural "get in and drive" gesture.
309
+ Piped, redirected, or otherwise non-interactive, bare `convertible` prints usage
310
+ instead, so scripts and agents keep a discoverable surface.
311
+
283
312
  The session loops until the user enters `q`, `quit`, or an empty line. Any
284
313
  driver flags accepted by `drive` (`--engine`, `--no-pr`, `--base-url`, etc.)
285
314
  are also accepted by `session`.
@@ -316,7 +345,7 @@ rely on a non-existent flag.
316
345
 
317
346
  | Verb | What it does |
318
347
  |------|--------------|
319
- | `drive <instruction>` | Run a repo task through a coder engine; write the artifact; hand off. |
348
+ | `drive <goal>` | Drive toward a goal/instruction: work autonomously through a coder engine; write the artifact; hand off. |
320
349
  | `drive --command <name> [args…]` | Expand a saved command template and drive it. |
321
350
  | `commands list` | List discovered command templates for a repo. |
322
351
  | `commands overview` | Describe the commands surface. |
@@ -61,6 +61,17 @@ def _argv_has_json(argv: list[str] | None) -> bool:
61
61
  return any(t == "--json" or t.startswith("--json=") for t in tokens)
62
62
 
63
63
 
64
+ def _stdio_is_interactive() -> bool:
65
+ """Whether stdin and stdout are both interactive terminals.
66
+
67
+ Bare ``convertible`` opens the interactive harness only at a real terminal;
68
+ isolated as a module function so tests can force the interactive branch
69
+ without a TTY (mirrors :func:`convertible.cli._banner._isatty`). Both streams
70
+ must be a TTY: the palette reads from stdin and renders its chrome to stdout.
71
+ """
72
+ return sys.stdin.isatty() and sys.stdout.isatty()
73
+
74
+
64
75
  def _build_parser() -> argparse.ArgumentParser:
65
76
  from convertible.cli._commands import cli as _cli_group
66
77
  from convertible.cli._commands import commands as _commands_group
@@ -136,6 +147,14 @@ def main(argv: list[str] | None = None) -> int:
136
147
  args = parser.parse_args(argv)
137
148
 
138
149
  if args.command is None:
150
+ # Bare `convertible` opens the interactive harness at a terminal; piped /
151
+ # redirected / non-interactive it prints usage so scripts and agents keep
152
+ # a discoverable surface. `-h/--help` is handled by argparse before here,
153
+ # so the help surface (and the teken rubric, which probes --help) stay
154
+ # available either way. Re-parsing ["session"] reuses the session
155
+ # subparser's defaults and func wiring — no parallel code path.
156
+ if _stdio_is_interactive():
157
+ return _dispatch(parser.parse_args(["session"]))
139
158
  parser.print_help()
140
159
  return 0
141
160
 
@@ -224,7 +224,10 @@ def cmd_drive(args: argparse.Namespace) -> int:
224
224
  def register(sub: argparse._SubParsersAction) -> None:
225
225
  p = sub.add_parser(
226
226
  "drive",
227
- help="Run a repo task through a coder engine and hand off the result.",
227
+ help=(
228
+ "Drive toward a goal: work autonomously on a request or instruction "
229
+ "through a coder engine, then hand off the result."
230
+ ),
228
231
  )
229
232
  # ``instruction`` is now zero-or-more positional tokens (nargs="*") so
230
233
  # ``--command`` can be the sole input without argparse raising an error.
@@ -232,7 +235,7 @@ def register(sub: argparse._SubParsersAction) -> None:
232
235
  "instruction",
233
236
  nargs="*",
234
237
  help=(
235
- "What the engine should do in the repo. "
238
+ "A goal or instruction to pursue autonomously. "
236
239
  "Mutually exclusive with --command. "
237
240
  "When --command is used, any positional tokens are passed as template arguments."
238
241
  ),
@@ -18,9 +18,13 @@ A clonable template for AgentCulture mesh agents. It carries an agent-first CLI
18
18
  buildable/deployable package baseline. Clone it, rename the package, edit
19
19
  `culture.yaml`, and you have a new agent.
20
20
 
21
+ Run `convertible` with no verb at a terminal to open the interactive harness (the
22
+ `session` palette); piped or non-interactive, it prints this usage instead.
23
+
21
24
  ## Verbs
22
25
 
23
- - `convertible drive <instruction>` — run a repo task through a coder engine.
26
+ - `convertible drive <goal>` — drive toward a goal/instruction; work autonomously
27
+ through a coder engine and hand off the result.
24
28
  - `convertible session` — foreground interactive palette over the drive path.
25
29
  - `convertible wheels list` — list discovered engine wheels.
26
30
  - `convertible whoami` — identity probe from `culture.yaml`.
@@ -122,10 +126,11 @@ itself (distinct from the global `overview`, which describes the agent).
122
126
  _DRIVE = """\
123
127
  # convertible drive
124
128
 
125
- Run a repo task through a coder engine: select an engine wheel, run the bounded
126
- agentic tool-loop against the repo, write a result artifact, and hand off the
127
- change as a branch + PR. The same invocation works for every engine — only
128
- `--engine` changes.
129
+ Drive toward a goal: hand convertible a request or instruction and it works
130
+ autonomously selecting an engine wheel, running the bounded agentic tool-loop,
131
+ writing a result artifact, and handing off the change as a branch + PR. The repo
132
+ is the target (`--repo`, default cwd); the same invocation works for every
133
+ engine — only `--engine` changes.
129
134
 
130
135
  ## Usage
131
136
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "convertible-cli"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  description = "Convertible CLI is a swappable coder-agent harness that turns different models into repo workers behind one shared task contract."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -18,12 +18,34 @@ def test_version_flag(capsys: pytest.CaptureFixture[str]) -> None:
18
18
  assert __version__ in capsys.readouterr().out
19
19
 
20
20
 
21
- def test_no_args_prints_help(capsys: pytest.CaptureFixture[str]) -> None:
21
+ def test_no_args_non_tty_prints_help(
22
+ capsys: pytest.CaptureFixture[str], monkeypatch: pytest.MonkeyPatch
23
+ ) -> None:
24
+ # Force the non-interactive branch so this is deterministic regardless of
25
+ # pytest's capture mode: under `pytest -s` from a real terminal stdin/stdout
26
+ # would be TTYs and bare invocation would otherwise open the session loop
27
+ # (and block on input()). Non-interactive must fall back to usage, preserving
28
+ # the discoverable surface for scripts and agents.
29
+ monkeypatch.setattr("convertible.cli._stdio_is_interactive", lambda: False)
22
30
  rc = main([])
23
31
  assert rc == 0
24
32
  assert "usage: convertible" in capsys.readouterr().out
25
33
 
26
34
 
35
+ def test_no_args_tty_opens_session(
36
+ capsys: pytest.CaptureFixture[str], monkeypatch: pytest.MonkeyPatch
37
+ ) -> None:
38
+ # At an interactive terminal, bare `convertible` opens the session harness.
39
+ # Force the interactive branch via the isolated seam, and stub input() to a
40
+ # quit token so the session renders its palette header then exits cleanly.
41
+ monkeypatch.setattr("convertible.cli._stdio_is_interactive", lambda: True)
42
+ monkeypatch.setattr("builtins.input", lambda *a, **k: "q")
43
+ rc = main([])
44
+ assert rc == 0
45
+ out = capsys.readouterr().out
46
+ assert "convertible session" in out
47
+
48
+
27
49
  def test_unknown_command_errors(capsys: pytest.CaptureFixture[str]) -> None:
28
50
  with pytest.raises(SystemExit) as exc:
29
51
  main(["bogus"])
@@ -72,7 +72,7 @@ wheels = [
72
72
 
73
73
  [[package]]
74
74
  name = "convertible-cli"
75
- version = "0.4.0"
75
+ version = "0.5.0"
76
76
  source = { editable = "." }
77
77
 
78
78
  [package.dev-dependencies]
File without changes
File without changes