codeplain 0.3.9__tar.gz → 0.3.10.dev1__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 (261) hide show
  1. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/workflows/e2e.yml +28 -1
  2. codeplain-0.3.10.dev1/.github/workflows/lint-powershell.yml +124 -0
  3. codeplain-0.3.10.dev1/.github/workflows/publish-dev-to-pypi.yml +135 -0
  4. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/workflows/publish-to-pypi.yml +14 -1
  5. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/CLAUDE.md +4 -4
  6. codeplain-0.3.10.dev1/CONTRIBUTING.md +137 -0
  7. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/PKG-INFO +36 -8
  8. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/README.md +31 -3
  9. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/concept_utils.py +6 -0
  10. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/docs/plain2code_cli.md +3 -3
  11. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/install/bash/install.sh +41 -0
  12. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/install/powershell/examples.ps1 +11 -5
  13. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/install/powershell/install.ps1 +131 -19
  14. codeplain-0.3.10.dev1/install/powershell/walkthrough.ps1 +174 -0
  15. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/module_renderer.py +6 -0
  16. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/partial_rendering.py +35 -4
  17. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code.py +31 -3
  18. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_arguments.py +7 -4
  19. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_console.py +3 -1
  20. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_exceptions.py +8 -0
  21. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_logger.py +37 -15
  22. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain_file.py +18 -1
  23. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain_modules.py +197 -7
  24. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/pyproject.toml +3 -3
  25. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/prepare_repositories.py +5 -0
  26. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/conformance_tests.py +40 -3
  27. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/implementation_code_helpers.py +5 -1
  28. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/render_context.py +13 -1
  29. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/requirements.txt +3 -3
  30. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/system_config.py +35 -0
  31. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_cli_output.py +13 -0
  32. codeplain-0.3.10.dev1/tests/test_headless_logging.py +177 -0
  33. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plain_modules.py +267 -1
  34. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plainfileparser.py +41 -4
  35. codeplain-0.3.10.dev1/tests/test_prepare_repositories_layout.py +277 -0
  36. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_system_config.py +37 -0
  37. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/plain_module_render_choice_tui.py +25 -8
  38. codeplain-0.3.9/install/powershell/walkthrough.ps1 +0 -161
  39. codeplain-0.3.9/tests/test_prepare_repositories_layout.py +0 -119
  40. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.claude/settings.json +0 -0
  41. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.flake8 +0 -0
  42. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/dependabot.yml +0 -0
  43. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/workflows/lint-and-test.yml +0 -0
  44. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
  45. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.github/workflows/publish-install-script.yml +0 -0
  46. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.gitignore +0 -0
  47. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.vscode/launch.json +0 -0
  48. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/.vscode/settings.json +0 -0
  49. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/LICENSE +0 -0
  50. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/change_detection.py +0 -0
  51. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/cli_output/__init__.py +0 -0
  52. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/cli_output/dry_run.py +0 -0
  53. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/cli_output/render_summary.py +0 -0
  54. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/cli_output/status.py +0 -0
  55. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/codeplain_REST_api.py +0 -0
  56. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/config/__init__.py +0 -0
  57. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/config/system_config.yaml +0 -0
  58. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/diff_utils.py +0 -0
  59. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/docs/generate_cli.py +0 -0
  60. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/docs/starting_a_plain_project_from_scratch.md +0 -0
  61. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/event_bus.py +0 -0
  62. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/config.yaml +0 -0
  63. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
  64. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
  65. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/run.sh +0 -0
  66. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/config.yaml +0 -0
  67. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
  68. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/hello_world_python.plain +0 -0
  69. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/run.sh +0 -0
  70. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/config.yaml +0 -0
  71. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
  72. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
  73. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
  74. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
  75. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
  76. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/hello_world_react.plain +0 -0
  77. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/run.sh +0 -0
  78. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/examples/run.sh +0 -0
  79. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/file_utils.py +0 -0
  80. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/git_utils.py +0 -0
  81. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/install/bash/examples.sh +0 -0
  82. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/install/bash/walkthrough.sh +0 -0
  83. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/memory_management.py +0 -0
  84. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/metadata_utils.py +0 -0
  85. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/path_resolution.py +0 -0
  86. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_cli.md +0 -0
  87. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_events.py +0 -0
  88. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_nodes.py +0 -0
  89. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_read_config.py +0 -0
  90. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_state.py +0 -0
  91. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_telemetry.py +0 -0
  92. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain2code_utils.py +0 -0
  93. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/plain_spec.py +0 -0
  94. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/pytest.ini +0 -0
  95. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/__init__.py +0 -0
  96. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
  97. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/base_action.py +0 -0
  98. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
  99. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/commit_implementation_code_changes.py +0 -0
  100. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/create_dist.py +0 -0
  101. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/exit_with_error.py +0 -0
  102. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/finish_functional_requirement.py +0 -0
  103. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/fix_conformance_test.py +0 -0
  104. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/fix_unit_tests.py +0 -0
  105. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/prepare_testing_environment.py +0 -0
  106. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/refactor_code.py +0 -0
  107. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/render_conformance_tests.py +0 -0
  108. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/render_functional_requirement.py +0 -0
  109. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/run_conformance_tests.py +0 -0
  110. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/run_unit_tests.py +0 -0
  111. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/actions/summarize_conformance_tests.py +0 -0
  112. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/code_renderer.py +0 -0
  113. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/render_types.py +0 -0
  114. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/render_utils.py +0 -0
  115. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/state_machine_config.py +0 -0
  116. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/states.py +0 -0
  117. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/render_machine/triggers.py +0 -0
  118. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/resources/codeplain_overview.png +0 -0
  119. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/resources/plain_example.png +0 -0
  120. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/standard_template_library/golang-console-app-template.plain +0 -0
  121. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/standard_template_library/python-console-app-template.plain +0 -0
  122. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
  123. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/standard_template_library/typescript-react-app-template.plain +0 -0
  124. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
  125. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_cypress.sh +0 -0
  126. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
  127. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_golang.sh +0 -0
  128. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_python.ps1 +0 -0
  129. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_python.sh +0 -0
  130. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_flutter.ps1 +0 -0
  131. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_flutter.sh +0 -0
  132. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_golang.ps1 +0 -0
  133. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_golang.sh +0 -0
  134. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_python.ps1 +0 -0
  135. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_python.sh +0 -0
  136. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_react.ps1 +0 -0
  137. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_react.sh +0 -0
  138. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/__init__.py +0 -0
  139. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/conftest.py +0 -0
  140. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
  141. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
  142. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_1.plain +0 -0
  143. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_2.plain +0 -0
  144. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_main.plain +0 -0
  145. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_1.plain +0 -0
  146. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_2.plain +0 -0
  147. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_common.plain +0 -0
  148. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_imports_main.plain +0 -0
  149. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/import_with_functionalities.plain +0 -0
  150. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
  151. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/imports/non_existent_import.plain +0 -0
  152. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_code_var.plain +0 -0
  153. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_implement.plain +0 -0
  154. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_leaf.plain +0 -0
  155. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_middle.plain +0 -0
  156. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_root.plain +0 -0
  157. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_solo.plain +0 -0
  158. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
  159. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
  160. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
  161. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/invalid_specification_order.plain +0 -0
  162. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
  163. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
  164. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
  165. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
  166. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
  167. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
  168. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
  169. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
  170. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
  171. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
  172. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
  173. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
  174. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
  175. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
  176. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
  177. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
  178. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
  179. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
  180. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts.plain +0 -0
  181. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
  182. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
  183. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
  184. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
  185. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
  186. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
  187. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
  188. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
  189. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
  190. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
  191. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
  192. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
  193. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts.plain +0 -0
  194. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
  195. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
  196. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
  197. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
  198. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
  199. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
  200. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
  201. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
  202. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/topological_sort.plain +0 -0
  203. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
  204. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/circular_requires_main.plain +0 -0
  205. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/circular_requires_sub.plain +0 -0
  206. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_1.plain +0 -0
  207. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_2.plain +0 -0
  208. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_common.plain +0 -0
  209. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_main.plain +0 -0
  210. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_1.plain +0 -0
  211. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_2.plain +0 -0
  212. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_main.plain +0 -0
  213. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/non_existent_require.plain +0 -0
  214. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_1.plain +0 -0
  215. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_2.plain +0 -0
  216. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_common.plain +0 -0
  217. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_main.plain +0 -0
  218. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/sample_base64_image.txt +0 -0
  219. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/simple.plain +0 -0
  220. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/block_level_include.plain +0 -0
  221. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/code_variables.plain +0 -0
  222. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/header.plain +0 -0
  223. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/implement.plain +0 -0
  224. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/implement_2.plain +0 -0
  225. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/template_include.plain +0 -0
  226. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/data/templates/test_hardest_problem.plain +0 -0
  227. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/e2e/Dockerfile +0 -0
  228. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/e2e/conftest.py +0 -0
  229. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/e2e/test_hello_world_python.py +0 -0
  230. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/e2e/test_hello_world_python_windows.py +0 -0
  231. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_arg_provenance.py +0 -0
  232. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_change_detection.py +0 -0
  233. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_console_log_styles.py +0 -0
  234. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_file_utils.py +0 -0
  235. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_folder_path_resolution.py +0 -0
  236. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_git_utils.py +0 -0
  237. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_imports.py +0 -0
  238. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_log_file_name_resolution.py +0 -0
  239. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_logging_config_path_resolution.py +0 -0
  240. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_partial_rendering.py +0 -0
  241. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_path_resolution.py +0 -0
  242. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plain2code.py +0 -0
  243. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plain2code_state.py +0 -0
  244. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plain2code_utils.py +0 -0
  245. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plainfile.py +0 -0
  246. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_plainspec.py +0 -0
  247. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_requires.py +0 -0
  248. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_resolve_config_file.py +0 -0
  249. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_script_path_resolution.py +0 -0
  250. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_telemetry.py +0 -0
  251. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_tui_usage.py +0 -0
  252. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tests/test_usage_summary.py +0 -0
  253. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/__init__.py +0 -0
  254. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/components.py +0 -0
  255. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/models.py +0 -0
  256. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/plain2code_tui.py +0 -0
  257. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/spinner.py +0 -0
  258. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/state_handlers.py +0 -0
  259. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/styles.css +0 -0
  260. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/tui/widget_helpers.py +0 -0
  261. {codeplain-0.3.9 → codeplain-0.3.10.dev1}/usage_summary.py +0 -0
@@ -59,4 +59,31 @@ jobs:
59
59
  - name: Run E2E tests
60
60
  env:
61
61
  CODEPLAIN_API_KEY: ${{ secrets.CODEPLAIN_API_KEY }}
62
- run: pytest tests/e2e/ -v --tb=short
62
+ run: pytest tests/e2e/ -v --tb=short
63
+
64
+ notify-on-failure:
65
+ name: Notify Slack on failure
66
+ needs: [e2e-linux, e2e-windows]
67
+ if: failure()
68
+ runs-on: ubuntu-latest
69
+ env:
70
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_E2E_WEBHOOK_URL }}
71
+ steps:
72
+ - name: Determine failed platforms
73
+ id: platforms
74
+ run: |
75
+ failed=""
76
+ [ "${{ needs.e2e-linux.result }}" = "failure" ] && failed="Linux"
77
+ if [ "${{ needs.e2e-windows.result }}" = "failure" ]; then
78
+ [ -n "$failed" ] && failed="$failed and Windows" || failed="Windows"
79
+ fi
80
+ echo "failed=$failed" >> "$GITHUB_OUTPUT"
81
+
82
+ - name: Send failure notification to Slack
83
+ if: ${{ env.SLACK_WEBHOOK_URL != '' }}
84
+ uses: slackapi/slack-github-action@v1.24.0
85
+ with:
86
+ payload: |
87
+ {
88
+ "text": ${{ toJSON(format('[Codeplain Client] E2E tests FAILED on {0}. See <{1}/{2}/actions/runs/{3}|the run log>.', steps.platforms.outputs.failed, github.server_url, github.repository, github.run_id)) }}
89
+ }
@@ -0,0 +1,124 @@
1
+ name: PowerShell Install Scripts
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - 'install/powershell/*.ps1'
7
+ - '.github/workflows/lint-powershell.yml'
8
+ pull_request:
9
+ paths:
10
+ - 'install/powershell/*.ps1'
11
+ - '.github/workflows/lint-powershell.yml'
12
+ workflow_dispatch:
13
+
14
+ jobs:
15
+ parse-windows-powershell-51:
16
+ name: Parse under Windows PowerShell 5.1
17
+ runs-on: windows-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ # The install scripts are fetched over HTTP and executed on stock Windows,
22
+ # where powershell.exe (5.1) is the default shell. 5.1 reads BOM-less files
23
+ # as ANSI (CP1252), so a non-ASCII glyph such as U+2713 decodes into a smart
24
+ # quote that silently terminates the enclosing string. The resulting parse
25
+ # errors point at unrelated lines far below the real cause, so parse every
26
+ # script with 5.1 explicitly rather than relying on PowerShell 7.
27
+ - name: Parse each script with 5.1
28
+ shell: powershell
29
+ run: |
30
+ $ErrorActionPreference = 'Stop'
31
+ Write-Host "PowerShell $($PSVersionTable.PSVersion) / ANSI codepage $([System.Text.Encoding]::Default.WebName)"
32
+
33
+ $failed = $false
34
+ Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
35
+ $errors = $null
36
+ [System.Management.Automation.Language.Parser]::ParseFile(
37
+ $_.FullName, [ref]$null, [ref]$errors) | Out-Null
38
+
39
+ if ($errors -and $errors.Count -gt 0) {
40
+ $failed = $true
41
+ Write-Host "FAIL $($_.Name): $($errors.Count) parse error(s)"
42
+ $errors | Sort-Object { $_.Extent.StartLineNumber } | ForEach-Object {
43
+ Write-Host " L$($_.Extent.StartLineNumber): $($_.Message)"
44
+ }
45
+ } else {
46
+ Write-Host "OK $($_.Name)"
47
+ }
48
+ }
49
+
50
+ if ($failed) { exit 1 }
51
+
52
+ # A BOM would fix file-based parsing but break `irm ... | iex`: PowerShell 5.1
53
+ # decodes an HTTP text/* body with no charset as ISO-8859-1, turning the BOM
54
+ # into literal "i>>?" text and failing with
55
+ # "The term 'i>>?$ErrorActionPreference' is not recognized".
56
+ # Keeping the sources pure ASCII is what makes both paths safe, so enforce it.
57
+ - name: Require pure ASCII and no BOM
58
+ shell: powershell
59
+ run: |
60
+ $ErrorActionPreference = 'Stop'
61
+ $failed = $false
62
+
63
+ Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
64
+ $fileBad = $false
65
+ $bytes = [System.IO.File]::ReadAllBytes($_.FullName)
66
+
67
+ if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
68
+ $failed = $true
69
+ $fileBad = $true
70
+ Write-Host "FAIL $($_.Name): has a UTF-8 BOM (breaks 'irm | iex'); remove it"
71
+ }
72
+
73
+ # Report line/column of any byte outside ASCII so the fix is obvious.
74
+ $text = [System.Text.Encoding]::UTF8.GetString($bytes)
75
+ $lineNo = 0
76
+ foreach ($line in ($text -split "`r?`n")) {
77
+ $lineNo++
78
+ for ($i = 0; $i -lt $line.Length; $i++) {
79
+ if ([int]$line[$i] -gt 127) {
80
+ $failed = $true
81
+ $fileBad = $true
82
+ $cp = "U+{0:X4}" -f [int]$line[$i]
83
+ Write-Host "FAIL $($_.Name) L${lineNo} C$($i + 1): non-ASCII $cp"
84
+ Write-Host " build it from its code point instead, e.g. `$CHECK = [char]0x2713"
85
+ break
86
+ }
87
+ }
88
+ }
89
+
90
+ if (-not $fileBad) { Write-Host "OK $($_.Name)" }
91
+ }
92
+
93
+ if ($failed) { exit 1 }
94
+
95
+ parse-powershell-7:
96
+ name: Parse under PowerShell 7
97
+ runs-on: windows-latest
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+
101
+ - name: Parse each script with 7
102
+ shell: pwsh
103
+ run: |
104
+ $ErrorActionPreference = 'Stop'
105
+ Write-Host "PowerShell $($PSVersionTable.PSVersion)"
106
+
107
+ $failed = $false
108
+ Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
109
+ $errors = $null
110
+ [System.Management.Automation.Language.Parser]::ParseFile(
111
+ $_.FullName, [ref]$null, [ref]$errors) | Out-Null
112
+
113
+ if ($errors -and $errors.Count -gt 0) {
114
+ $failed = $true
115
+ Write-Host "FAIL $($_.Name): $($errors.Count) parse error(s)"
116
+ $errors | Sort-Object { $_.Extent.StartLineNumber } | ForEach-Object {
117
+ Write-Host " L$($_.Extent.StartLineNumber): $($_.Message)"
118
+ }
119
+ } else {
120
+ Write-Host "OK $($_.Name)"
121
+ }
122
+ }
123
+
124
+ if ($failed) { exit 1 }
@@ -0,0 +1,135 @@
1
+ name: Publish dev build to PyPI
2
+
3
+ # Every merge to main publishes a PEP 440 dev release (e.g. 0.3.10.dev7) to
4
+ # PyPI, so the latest main is always installable from the real index with real
5
+ # dependency resolution. Dev releases are pre-releases: pip and uv skip them
6
+ # unless asked, so ordinary installs keep getting the latest stable.
7
+ #
8
+ # Tagged releases (including rc/beta/alpha) are handled by publish-to-pypi.yml.
9
+ on:
10
+ push:
11
+ branches: [main]
12
+ # Ad-hoc runs, e.g. re-publishing after a PyPI outage.
13
+ workflow_dispatch:
14
+
15
+ # Least privilege by default: jobs get no GITHUB_TOKEN scopes unless they
16
+ # opt in below.
17
+ permissions: {}
18
+
19
+ # Serialize publishes so versions land in merge order. Queued runs are not
20
+ # cancelled — each merge should still get its own dev build.
21
+ concurrency:
22
+ group: publish-dev-to-pypi
23
+ cancel-in-progress: false
24
+
25
+ jobs:
26
+ build:
27
+ name: Build dev distribution
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ contents: read
31
+ outputs:
32
+ should-publish: ${{ steps.version.outputs.should-publish }}
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ with:
37
+ # hatch-vcs derives the version from git tags, so we need full history.
38
+ fetch-depth: 0
39
+
40
+ - name: Install uv
41
+ # uv provisions its own Python (honoring requires-python), so no
42
+ # separate actions/setup-python step is needed.
43
+ run: |
44
+ curl -LsSf https://astral.sh/uv/install.sh | sh
45
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
46
+
47
+ - name: Compute dev version
48
+ id: version
49
+ # Between releases hatch-vcs produces something like
50
+ # "0.3.10.dev16+gb710c2982". The "+g..." local version segment is valid
51
+ # PEP 440 but is rejected by PyPI on upload, so it has to go. We keep
52
+ # setuptools-scm's own next-version guess (0.3.10 — the patch bump
53
+ # after the latest tag) rather than re-deriving it here, and use the
54
+ # run number as the dev counter: it is strictly increasing, so each
55
+ # merge sorts after the last and re-runs never collide.
56
+ run: |
57
+ RAW=$(uvx --from setuptools-scm python -c \
58
+ "from setuptools_scm import get_version; print(get_version())")
59
+ echo "setuptools-scm reports: $RAW"
60
+
61
+ # On a commit that IS a release tag, setuptools-scm returns a clean
62
+ # version with no .dev component (e.g. "0.3.9" or "0.4.0rc1").
63
+ # Appending ".dev<run>" to that yields 0.3.9.dev42, which sorts BELOW
64
+ # the released 0.3.9 — newer code would look older. A tagged commit
65
+ # is a real release and is published by publish-to-pypi.yml, so there
66
+ # is no dev build to make here.
67
+ case "$RAW" in
68
+ *.dev*) ;;
69
+ *)
70
+ echo "::notice::$RAW is a tagged release; skipping dev build."
71
+ echo "should-publish=false" >> $GITHUB_OUTPUT
72
+ exit 0
73
+ ;;
74
+ esac
75
+
76
+ BASE=${RAW%%+*}
77
+ BASE=${BASE%%.dev*}
78
+ VERSION="${BASE}.dev${GITHUB_RUN_NUMBER}"
79
+ echo "Derived version: $RAW -> $VERSION"
80
+ echo "SETUPTOOLS_SCM_PRETEND_VERSION=$VERSION" >> $GITHUB_ENV
81
+ echo "should-publish=true" >> $GITHUB_OUTPUT
82
+
83
+ - name: Build package
84
+ if: steps.version.outputs.should-publish == 'true'
85
+ # hatch-vcs reads SETUPTOOLS_SCM_PRETEND_VERSION in place of the tag.
86
+ run: |
87
+ uv build
88
+ echo "Built distributions:"
89
+ ls -l dist/
90
+
91
+ - name: Store the distribution packages
92
+ if: steps.version.outputs.should-publish == 'true'
93
+ uses: actions/upload-artifact@v4
94
+ with:
95
+ name: dev-package-distributions
96
+ path: dist/
97
+
98
+ publish-dev:
99
+ name: Publish dev build to PyPI
100
+ needs: build
101
+ if: needs.build.outputs.should-publish == 'true'
102
+ runs-on: ubuntu-latest
103
+ environment:
104
+ name: pypi
105
+ url: https://pypi.org/p/codeplain
106
+ permissions:
107
+ # Mint a short-lived OIDC token so PyPI Trusted Publishing can
108
+ # authenticate this run — no long-lived API token needed.
109
+ id-token: write
110
+
111
+ env:
112
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
113
+
114
+ steps:
115
+ - name: Download distribution packages
116
+ uses: actions/download-artifact@v4
117
+ with:
118
+ name: dev-package-distributions
119
+ path: dist/
120
+
121
+ - name: Publish to PyPI
122
+ uses: pypa/gh-action-pypi-publish@release/v1
123
+ with:
124
+ # PyPI uploads are immutable, so a re-run of an already-published
125
+ # version should be a no-op, not a red build.
126
+ skip-existing: true
127
+
128
+ # Success is deliberately quiet: this runs on every merge to main, which
129
+ # is already announced elsewhere. Only failures ping.
130
+ - name: Notify Slack (failure)
131
+ if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
132
+ run: |
133
+ curl -s -X POST "$SLACK_WEBHOOK_URL" \
134
+ -H 'Content-type: application/json' \
135
+ --data "{\"text\":\"*Codeplain Client*: Publishing dev build to PyPI FAILED :x: (commit \`${{ github.sha }}\`). See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
@@ -91,10 +91,23 @@ jobs:
91
91
 
92
92
  - name: Notify Slack (success)
93
93
  if: ${{ success() && env.SLACK_WEBHOOK_URL != '' }}
94
+ env:
95
+ # GitHub marks the release itself as a pre-release; the tag
96
+ # (v0.4.0rc1) carries the same intent for PEP 440.
97
+ IS_PRERELEASE: ${{ github.event.release.prerelease }}
98
+ TAG: ${{ github.ref_name }}
94
99
  run: |
100
+ VERSION="${TAG#v}"
101
+ if [ "$IS_PRERELEASE" = "true" ]; then
102
+ # pip and uv skip pre-releases by default, so "--upgrade" would
103
+ # NOT pick this up. Tell people the command that actually works.
104
+ TEXT="*Codeplain Client*: pre-release \`$TAG\` published to PyPI :test_tube:. Normal installs are unaffected — try it with \`pip install --pre codeplain==$VERSION\`."
105
+ else
106
+ TEXT="*Codeplain Client*: \`$TAG\` published to PyPI :white_check_mark:. Install with \`pip install --upgrade codeplain\`."
107
+ fi
95
108
  curl -s -X POST "$SLACK_WEBHOOK_URL" \
96
109
  -H 'Content-type: application/json' \
97
- --data "{\"text\":\"*Codeplain Client*: \`${{ github.ref_name }}\` published to PyPI :white_check_mark:. Install with \`pip install --upgrade codeplain\`.\"}"
110
+ --data "$(jq -n --arg t "$TEXT" '{text:$t}')"
98
111
 
99
112
  - name: Notify Slack (failure)
100
113
  if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
@@ -14,14 +14,14 @@ The codebase serves two audiences:
14
14
  - **End users**: developers who write `***plain` specs and run `plain2code.py` to generate code
15
15
  - **Internal devs**: maintaining the renderer itself (this codebase)
16
16
 
17
- ### Related Repository: plain2code_rest_api
17
+ ### Related Repository: codeplain-api
18
18
 
19
- This repository has a sibling repository **`plain2code_rest_api`** which contains the backend API service that this client communicates with. The two repositories are typically cloned as siblings:
19
+ This repository has a sibling repository **`codeplain-api`** which contains the backend API service that this client communicates with. The two repositories are typically cloned as siblings:
20
20
 
21
21
  ```
22
22
  parent-directory/
23
- ├── codeplain/ # This repository (client)
24
- └── plain2code_rest_api/ # Backend API service
23
+ ├── codeplain/ # This repository (client)
24
+ └── codeplain-api/ # Backend API service
25
25
  ```
26
26
 
27
27
  **When to work across both repositories:**
@@ -0,0 +1,137 @@
1
+ # Contributing to Codeplain
2
+
3
+ Thanks for contributing to Codeplain.
4
+
5
+ ## Before You Start
6
+
7
+ Check existing issues and pull requests before starting work.
8
+
9
+ Keep each contribution focused on one issue or a closely related set of changes.
10
+
11
+ ## Contribution Workflow
12
+
13
+ 1. Fork the Codeplain repository.
14
+ 2. Make your changes on a branch in your fork.
15
+ 3. Commit and push the changes to your fork.
16
+ 4. Open a pull request against the Codeplain `main` branch.
17
+
18
+ ## Configure Codeplain
19
+
20
+ Use your own Codeplain API key for local development and testing.
21
+
22
+ Never commit API keys, credentials, or other secrets.
23
+
24
+ ## Test with a Plain Example
25
+
26
+ When relevant, test your change with an existing example from the `plainlang-examples` repository.
27
+
28
+ This provides a real `.plain` project for verifying the change in an actual Codeplain workflow.
29
+
30
+ ## Run Tests
31
+
32
+ Run the tests relevant to your change before opening a pull request.
33
+
34
+ For changes that affect the CLI, rendering, or test execution, also test the change by running the relevant Codeplain command from the terminal.
35
+
36
+ Check that:
37
+
38
+ * the command returns the expected exit code,
39
+ * errors are clear and do not expose unintended tracebacks,
40
+ * existing Codeplain behavior still works.
41
+
42
+ For platform-specific changes, test the relevant `.sh` or `.ps1` workflow.
43
+
44
+ ## Keep the Change Clean
45
+
46
+ Before submitting:
47
+
48
+ * remove temporary files and debugging output,
49
+ * avoid unrelated changes,
50
+ * add or update tests where needed,
51
+ * update documentation when behavior changes,
52
+ * verify that no secrets are included.
53
+
54
+ Review your changes with:
55
+
56
+ ```bash
57
+ git status
58
+ git diff
59
+ ```
60
+
61
+ ## Pull Request
62
+
63
+ Include:
64
+
65
+ * what changed,
66
+ * why it changed,
67
+ * the related issue, when applicable,
68
+ * how the change was tested,
69
+ * the `plainlang-examples` example used, when relevant.
70
+
71
+ ## Pre-Releases
72
+
73
+ Everything below happens on real PyPI — there is no separate test index.
74
+ Pre-releases are invisible to ordinary installs: pip and uv skip them during
75
+ resolution, so `pip install codeplain` and `pip install --upgrade codeplain`
76
+ always serve the latest *stable* release.
77
+
78
+ ### Dev builds (automatic)
79
+
80
+ Every merge to `main` publishes a dev release such as `0.3.10.dev7`, so the tip
81
+ of main is always installable from the real index:
82
+
83
+ ```bash
84
+ pip install --pre codeplain==0.3.10.dev7
85
+ uv tool install --prerelease allow codeplain
86
+ ```
87
+
88
+ Versions are `<next-patch>.dev<run-number>`, so they sort after the last
89
+ release and before the next one. See `.github/workflows/publish-dev-to-pypi.yml`.
90
+ If that workflow is ever dispatched against a commit that is itself a release
91
+ tag, it skips rather than publishing a dev build that would sort below the
92
+ release.
93
+
94
+ ### Release candidates (manual)
95
+
96
+ To get a specific build in front of people before it becomes the default
97
+ install, cut a PEP 440 pre-release.
98
+
99
+ Tag and publish a GitHub release as usual, but with a pre-release version and
100
+ the release marked "pre-release":
101
+
102
+ ```
103
+ v0.4.0a1 alpha
104
+ v0.4.0b1 beta
105
+ v0.4.0rc1 release candidate
106
+ ```
107
+
108
+ `publish-to-pypi.yml` handles these with no special casing: hatch-vcs reads the
109
+ version straight off the tag (`v0.4.0rc1` -> `0.4.0rc1`).
110
+
111
+ Opt in the same way:
112
+
113
+ ```bash
114
+ pip install --pre codeplain==0.4.0rc1
115
+ ```
116
+
117
+ ### Which API a build talks to
118
+
119
+ Pre-release builds default to the **test** API, so an unreleased client is
120
+ exercised against the unreleased backend:
121
+
122
+ | build | default API |
123
+ | --- | --- |
124
+ | stable release (`0.3.9`) | `https://api.codeplain.ai` |
125
+ | dev build (`0.3.10.dev7`) | `https://api.test.codeplain.ai` |
126
+ | alpha/beta/rc (`0.4.0rc1`) | `https://api.test.codeplain.ai` |
127
+
128
+ `--api` always overrides this. Resolution lives in
129
+ `system_config._resolve_default_api_url`, keyed off the version baked into the
130
+ package at build time — so nothing needs configuring at install time.
131
+
132
+ A source checkout reports the nearest git tag as its version, so it is treated
133
+ as stable and keeps pointing at production; use `--api` to aim it elsewhere.
134
+
135
+ Because every build above goes to real PyPI, dependency resolution and the
136
+ install path are exactly what an end user gets — the main reason this is
137
+ preferred over publishing to TestPyPI.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: codeplain
3
- Version: 0.3.9
3
+ Version: 0.3.10.dev1
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
@@ -8,15 +8,15 @@ Classifier: Intended Audience :: Developers
8
8
  Classifier: Operating System :: OS Independent
9
9
  Classifier: Topic :: Software Development :: Code Generators
10
10
  Requires-Python: ==3.11.*
11
- Requires-Dist: gitpython==3.1.52
12
- Requires-Dist: mistletoe==1.5.1
11
+ Requires-Dist: gitpython==3.1.55
12
+ Requires-Dist: mistletoe==1.6.0
13
13
  Requires-Dist: networkx==3.6.1
14
14
  Requires-Dist: python-frontmatter==1.3.0
15
15
  Requires-Dist: python-liquid2==0.4.0
16
16
  Requires-Dist: pyyaml==6.0.3
17
17
  Requires-Dist: requests==2.34.2
18
18
  Requires-Dist: rich==15.0.0
19
- Requires-Dist: sentry-sdk==2.66.0
19
+ Requires-Dist: sentry-sdk==2.66.1
20
20
  Requires-Dist: textual>=7.5.0
21
21
  Requires-Dist: tiktoken==0.13.0
22
22
  Requires-Dist: transitions==0.9.3
@@ -52,6 +52,7 @@ macOS and Linux:
52
52
 
53
53
  ```bash
54
54
  curl -fsSL https://codeplain.ai/install.sh | bash
55
+ # re-run to update to the latest version
55
56
  ```
56
57
 
57
58
  Windows PowerShell:
@@ -74,12 +75,39 @@ export CODEPLAIN_API_KEY="your_actual_api_key_here"
74
75
 
75
76
  You describe what you want in plain English, an agent helps you write a spec in \*\*\*plain language, and \*codeplain renders the actual code. This is what [plain-forge](https://github.com/Codeplain-ai/plain-forge) sets up: a toolkit of skills, rules, and docs that plugs into your AI coding agent of choice — Claude Code, Codex, ForgeCode, OpenCode, or any other agent that reads from a standard skills directory — and turns a conversation into a complete `.plain` spec, then keeps maintaining it across the lifetime of the project.
76
77
 
77
- If you didn't install it during step 1, run it any time:
78
+ If you didn't install it during step 1, run it any time using your favorite Node package runner:
78
79
 
79
80
  ```bash
80
81
  npx plain-forge install
81
82
  ```
82
83
 
84
+ The same command works with any other runner — pick whichever matches your toolchain:
85
+
86
+ ```bash
87
+ # npm (bundled with Node.js)
88
+ npx plain-forge install
89
+
90
+ # pnpm
91
+ pnpm dlx plain-forge install
92
+
93
+ # Bun
94
+ bunx plain-forge install
95
+
96
+ # Yarn (Berry, v2+)
97
+ yarn dlx plain-forge install
98
+
99
+ # Deno (npm: specifier, needs permissions to write the skills directory)
100
+ deno run -A npm:plain-forge install
101
+ ```
102
+
103
+ Every runner downloads `plain-forge` on demand and runs it without adding it to your project's dependencies. The package exposes a `plain-forge` binary, so no runner needs an extra `--package` flag.
104
+
105
+ `install` fails if plain-forge is already installed at the target — to refresh an existing installation to the latest skills, rules, and docs, use `update` instead (swap in your runner of choice):
106
+
107
+ ```bash
108
+ npx plain-forge update
109
+ ```
110
+
83
111
  ### 3. Convert specs into tested and validated code
84
112
 
85
113
  \*codeplain extends coding agents with agentic skills for working at the specification layer, and with tools that convert specifications into tested and validated implementation code.
@@ -101,9 +129,9 @@ You can immediately test the system with a simple "Hello World" example:
101
129
 
102
130
  _Note: Rendering will take a few minutes to complete._
103
131
 
104
- - The system will generate a Python application in the `build` directory. You can run it with:
132
+ - The system will generate a Python application in the `dist` directory. You can run it with:
105
133
  ```bash
106
- cd build
134
+ cd dist
107
135
  python hello_world.py
108
136
  ```
109
137
 
@@ -22,6 +22,7 @@ macOS and Linux:
22
22
 
23
23
  ```bash
24
24
  curl -fsSL https://codeplain.ai/install.sh | bash
25
+ # re-run to update to the latest version
25
26
  ```
26
27
 
27
28
  Windows PowerShell:
@@ -44,12 +45,39 @@ export CODEPLAIN_API_KEY="your_actual_api_key_here"
44
45
 
45
46
  You describe what you want in plain English, an agent helps you write a spec in \*\*\*plain language, and \*codeplain renders the actual code. This is what [plain-forge](https://github.com/Codeplain-ai/plain-forge) sets up: a toolkit of skills, rules, and docs that plugs into your AI coding agent of choice — Claude Code, Codex, ForgeCode, OpenCode, or any other agent that reads from a standard skills directory — and turns a conversation into a complete `.plain` spec, then keeps maintaining it across the lifetime of the project.
46
47
 
47
- If you didn't install it during step 1, run it any time:
48
+ If you didn't install it during step 1, run it any time using your favorite Node package runner:
48
49
 
49
50
  ```bash
50
51
  npx plain-forge install
51
52
  ```
52
53
 
54
+ The same command works with any other runner — pick whichever matches your toolchain:
55
+
56
+ ```bash
57
+ # npm (bundled with Node.js)
58
+ npx plain-forge install
59
+
60
+ # pnpm
61
+ pnpm dlx plain-forge install
62
+
63
+ # Bun
64
+ bunx plain-forge install
65
+
66
+ # Yarn (Berry, v2+)
67
+ yarn dlx plain-forge install
68
+
69
+ # Deno (npm: specifier, needs permissions to write the skills directory)
70
+ deno run -A npm:plain-forge install
71
+ ```
72
+
73
+ Every runner downloads `plain-forge` on demand and runs it without adding it to your project's dependencies. The package exposes a `plain-forge` binary, so no runner needs an extra `--package` flag.
74
+
75
+ `install` fails if plain-forge is already installed at the target — to refresh an existing installation to the latest skills, rules, and docs, use `update` instead (swap in your runner of choice):
76
+
77
+ ```bash
78
+ npx plain-forge update
79
+ ```
80
+
53
81
  ### 3. Convert specs into tested and validated code
54
82
 
55
83
  \*codeplain extends coding agents with agentic skills for working at the specification layer, and with tools that convert specifications into tested and validated implementation code.
@@ -71,9 +99,9 @@ You can immediately test the system with a simple "Hello World" example:
71
99
 
72
100
  _Note: Rendering will take a few minutes to complete._
73
101
 
74
- - The system will generate a Python application in the `build` directory. You can run it with:
102
+ - The system will generate a Python application in the `dist` directory. You can run it with:
75
103
  ```bash
76
- cd build
104
+ cd dist
77
105
  python hello_world.py
78
106
  ```
79
107
 
@@ -12,8 +12,14 @@ from plain2code_exceptions import PlainSyntaxError
12
12
  DEFAULT_CONCEPTS = {
13
13
  ":ConformanceTests:",
14
14
  ":UnitTests:",
15
+ ":AcceptanceTest:",
15
16
  ":AcceptanceTests:",
16
17
  ":Implementation:",
18
+ ":plainDefinitions:",
19
+ ":plainImplementationReqs:",
20
+ ":plainFunctionality:",
21
+ ":plainTestReqs:",
22
+ ":plainImplementationCode:",
17
23
  }
18
24
 
19
25
 
@@ -118,9 +118,9 @@ options:
118
118
  If set, render the state machine graph.
119
119
  --logging-config-path LOGGING_CONFIG_PATH
120
120
  Path to the logging configuration file.
121
- --headless Run in headless mode: no TUI, no terminal output
122
- except a single render-started message. All logs are
123
- written to the log file.
121
+ --headless Run in headless mode: no TUI. Progress is written to
122
+ the log file and streamed to stdout as it happens; the
123
+ specification text itself stays in the log file only.
124
124
  --status Display account status including user information, API
125
125
  key label, and rendering credits. Does not render any
126
126
  code.