spawnio 1.0.9__tar.gz → 1.1.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 (162) hide show
  1. {spawnio-1.0.9 → spawnio-1.1.0}/PKG-INFO +40 -3
  2. {spawnio-1.0.9 → spawnio-1.1.0}/README.md +39 -2
  3. {spawnio-1.0.9 → spawnio-1.1.0}/docs/architecture.md +35 -2
  4. {spawnio-1.0.9 → spawnio-1.1.0}/docs/changelog.md +27 -0
  5. {spawnio-1.0.9 → spawnio-1.1.0}/docs/commands.md +66 -5
  6. {spawnio-1.0.9 → spawnio-1.1.0}/docs/getting-started.md +3 -2
  7. spawnio-1.1.0/docs/inspection/inspection-contract.md +987 -0
  8. spawnio-1.1.0/docs/inspection/language-framework-handoff.md +57 -0
  9. spawnio-1.1.0/docs/inspection/safe-discovery.md +123 -0
  10. spawnio-1.1.0/docs/inspection/supported-technologies.md +182 -0
  11. {spawnio-1.0.9 → spawnio-1.1.0}/pyproject.toml +1 -1
  12. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/__init__.py +1 -1
  13. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/cli/app.py +77 -2
  14. spawnio-1.1.0/src/spawn/cli/inspect_render.py +287 -0
  15. spawnio-1.1.0/src/spawn/inspection/__init__.py +69 -0
  16. spawnio-1.1.0/src/spawn/inspection/_reading.py +21 -0
  17. spawnio-1.1.0/src/spawn/inspection/base.py +68 -0
  18. spawnio-1.1.0/src/spawn/inspection/dependencies.py +410 -0
  19. spawnio-1.1.0/src/spawn/inspection/discovery.py +280 -0
  20. spawnio-1.1.0/src/spawn/inspection/exceptions.py +14 -0
  21. spawnio-1.1.0/src/spawn/inspection/frameworks.py +255 -0
  22. spawnio-1.1.0/src/spawn/inspection/languages.py +195 -0
  23. spawnio-1.1.0/src/spawn/inspection/models.py +615 -0
  24. spawnio-1.1.0/src/spawn/inspection/orchestrator.py +294 -0
  25. spawnio-1.1.0/src/spawn/inspection/serialization.py +491 -0
  26. spawnio-1.1.0/src/spawn/inspection/tooling.py +469 -0
  27. {spawnio-1.0.9 → spawnio-1.1.0}/tests/conftest.py +8 -0
  28. spawnio-1.1.0/tests/fixtures/inspection_corpus.py +175 -0
  29. spawnio-1.1.0/tests/fixtures/make_sample_report.py +363 -0
  30. spawnio-1.1.0/tests/fixtures/static/sample_report.json +316 -0
  31. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_app.py +15 -0
  32. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_boundaries.py +1 -1
  33. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_docs.py +3 -1
  34. spawnio-1.1.0/tests/test_inspect_cli.py +350 -0
  35. spawnio-1.1.0/tests/test_inspection_dependencies.py +537 -0
  36. spawnio-1.1.0/tests/test_inspection_discovery.py +530 -0
  37. spawnio-1.1.0/tests/test_inspection_frameworks.py +327 -0
  38. spawnio-1.1.0/tests/test_inspection_languages.py +221 -0
  39. spawnio-1.1.0/tests/test_inspection_models.py +773 -0
  40. spawnio-1.1.0/tests/test_inspection_orchestrator.py +445 -0
  41. spawnio-1.1.0/tests/test_inspection_regression.py +477 -0
  42. spawnio-1.1.0/tests/test_inspection_sample.py +486 -0
  43. spawnio-1.1.0/tests/test_inspection_serialization.py +791 -0
  44. spawnio-1.1.0/tests/test_inspection_tooling.py +605 -0
  45. {spawnio-1.0.9 → spawnio-1.1.0}/.gitignore +0 -0
  46. {spawnio-1.0.9 → spawnio-1.1.0}/CONTRIBUTING.md +0 -0
  47. {spawnio-1.0.9 → spawnio-1.1.0}/LICENSE +0 -0
  48. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/cli/__init__.py +0 -0
  49. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/cli/errors.py +0 -0
  50. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/cli/noninteractive.py +0 -0
  51. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/cli/prompts.py +0 -0
  52. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/__init__.py +0 -0
  53. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/exceptions.py +0 -0
  54. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/models.py +0 -0
  55. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/planning.py +0 -0
  56. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/project.py +0 -0
  57. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/core/registry.py +0 -0
  58. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/__init__.py +0 -0
  59. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/custom_structure.py +0 -0
  60. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/destination.py +0 -0
  61. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/metadata.py +0 -0
  62. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/pipeline.py +0 -0
  63. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/project_files.py +0 -0
  64. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/generators/project_generator.py +0 -0
  65. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/github/__init__.py +0 -0
  66. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/github/exceptions.py +0 -0
  67. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/github/publisher.py +0 -0
  68. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/github/validators.py +0 -0
  69. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/__init__.py +0 -0
  70. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/agent/__init__.py +0 -0
  71. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/agent/content.py +0 -0
  72. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/automation/__init__.py +0 -0
  73. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/automation/content.py +0 -0
  74. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/backend_api/__init__.py +0 -0
  75. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/backend_api/content.py +0 -0
  76. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/base.py +0 -0
  77. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/chatbot/__init__.py +0 -0
  78. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/chatbot/content.py +0 -0
  79. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/cli_application/__init__.py +0 -0
  80. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/cli_application/content.py +0 -0
  81. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/__init__.py +0 -0
  82. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/analysis/__init__.py +0 -0
  83. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/analysis/content.py +0 -0
  84. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/dashboard/__init__.py +0 -0
  85. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/dashboard/content.py +0 -0
  86. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/etl/__init__.py +0 -0
  87. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/etl/content.py +0 -0
  88. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/ml/__init__.py +0 -0
  89. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/data_project/ml/content.py +0 -0
  90. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/mcp_server/__init__.py +0 -0
  91. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/mcp_server/content.py +0 -0
  92. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/rag/__init__.py +0 -0
  93. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/rag/content.py +0 -0
  94. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/templates/shared_content.py +0 -0
  95. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/__init__.py +0 -0
  96. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/banner.py +0 -0
  97. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/console.py +0 -0
  98. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/doctor.py +0 -0
  99. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/doctor_fix.py +0 -0
  100. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/git.py +0 -0
  101. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/redact.py +0 -0
  102. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/success.py +0 -0
  103. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/theme.py +0 -0
  104. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/uv.py +0 -0
  105. {spawnio-1.0.9 → spawnio-1.1.0}/src/spawn/utils/validators.py +0 -0
  106. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/__init__.py +0 -0
  107. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/archetypes.py +0 -0
  108. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/static/broken_meta/.spawn/meta.json +0 -0
  109. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/static/meta_unknown_intent/.spawn/meta.json +0 -0
  110. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/static/non_spawn_python_repo/pyproject.toml +0 -0
  111. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/static/non_spawn_python_repo/src/pkg/__init__.py +0 -0
  112. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/static/non_spawn_python_repo/tests/test_x.py +0 -0
  113. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/agent.txt +0 -0
  114. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/automation.txt +0 -0
  115. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/backend-api.txt +0 -0
  116. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/chatbot.txt +0 -0
  117. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/cli.txt +0 -0
  118. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/custom.txt +0 -0
  119. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/data.txt +0 -0
  120. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/mcp.txt +0 -0
  121. {spawnio-1.0.9 → spawnio-1.1.0}/tests/fixtures/trees/rag.txt +0 -0
  122. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_agent_generator.py +0 -0
  123. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_agent_template.py +0 -0
  124. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_automation_generator.py +0 -0
  125. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_automation_template.py +0 -0
  126. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_chatbot_generator.py +0 -0
  127. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_chatbot_template.py +0 -0
  128. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_cli_application_generator.py +0 -0
  129. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_cli_application_template.py +0 -0
  130. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_console.py +0 -0
  131. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_create_flags.py +0 -0
  132. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_custom_structure.py +0 -0
  133. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_custom_structure_integration.py +0 -0
  134. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_data_project_analysis.py +0 -0
  135. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_data_project_dashboard.py +0 -0
  136. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_data_project_etl.py +0 -0
  137. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_data_project_gitignore.py +0 -0
  138. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_data_project_ml.py +0 -0
  139. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_destination.py +0 -0
  140. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_doctor.py +0 -0
  141. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_doctor_fix.py +0 -0
  142. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_errors.py +0 -0
  143. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_fixtures.py +0 -0
  144. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_generator.py +0 -0
  145. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_git.py +0 -0
  146. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_github_publisher.py +0 -0
  147. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_github_validators.py +0 -0
  148. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_mcp_server_generator.py +0 -0
  149. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_mcp_server_template.py +0 -0
  150. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_models.py +0 -0
  151. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_noninteractive.py +0 -0
  152. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_pipeline.py +0 -0
  153. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_planning.py +0 -0
  154. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_project.py +0 -0
  155. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_project_files.py +0 -0
  156. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_prompts.py +0 -0
  157. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_rag_generator.py +0 -0
  158. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_rag_template.py +0 -0
  159. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_registry.py +0 -0
  160. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_templates.py +0 -0
  161. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_uv.py +0 -0
  162. {spawnio-1.0.9 → spawnio-1.1.0}/tests/test_validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: spawnio
3
- Version: 1.0.9
3
+ Version: 1.1.0
4
4
  Summary: Spawn a ready-to-use Python project in seconds
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -89,6 +89,7 @@ It's repetitive. It's inconsistent. And you haven't written a single line of *re
89
89
  | **GitHub publishing** | Connects your project to an existing GitHub repo and pushes the initial commit |
90
90
  | **spawn doctor** | Scores your project's health out of 100, with per-category breakdowns and a prioritized next step |
91
91
  | **spawn doctor --fix** | Fixes missing files and config automatically — never overwrites, never installs packages |
92
+ | **spawn inspect** | Static, read-only summary of a repository: languages, frameworks, dependencies, package managers, tooling and layout, as text or JSON |
92
93
 
93
94
  ---
94
95
 
@@ -144,12 +145,13 @@ Running `spawn` with no arguments shows the banner, the installed version, and t
144
145
 
145
146
  ```
146
147
  SPAWN — scaffold your next project
147
- v1.0.9
148
+ v1.1.0
148
149
 
149
150
  Commands
150
151
  create Scaffold a new project
151
152
  doctor Check the health of a project directory
152
153
  version Show the installed version
154
+ inspect Inspect a repository (read-only)
153
155
 
154
156
  Run spawn COMMAND --help for details on a command.
155
157
  ```
@@ -791,8 +793,42 @@ spawn doctor --fix --license mit
791
793
 
792
794
  ```bash
793
795
  spawn version
794
- # → Spawn v1.0.9
796
+ # → Spawn v1.1.0
797
+
798
+ spawn --version
799
+ # → Spawn v1.1.0
800
+ ```
801
+
802
+ ### `spawn inspect`
803
+
804
+ Give Spawn a repository and receive a deterministic, evidence-backed summary of what it contains.
805
+
806
+ ```bash
807
+ spawn inspect . # human-readable summary
808
+ spawn inspect . --json # full report on stdout, schema_version "1.0"
809
+ spawn inspect . --verbose # all dependencies, entries and evidence paths
810
+ ```
811
+
795
812
  ```
813
+ ⚡ SPAWN / INSPECT
814
+
815
+ demo
816
+ python project · 11 files · 3 directories
817
+
818
+ PROJECT OVERVIEW
819
+ Primary language python
820
+ Framework Not detected
821
+ Package manager Not detected
822
+ Origin spawn
823
+
824
+ ✓ Inspection complete
825
+ ```
826
+
827
+ **Scope.** 25 languages by extension and manifest; React, Next.js, Vue, Nuxt, Angular, Svelte, Express, FastAPI, Flask, Django, Starlette, Pydantic and Laravel; dependencies from `pyproject.toml`, `requirements*.txt` and `package.json`; package managers (uv, poetry, pipenv, pip, npm, yarn, pnpm, bun); tooling (ruff, black, flake8, mypy, pyright, pytest, eslint, prettier, jest, vitest, pre-commit, git), CI, containers and databases. Full matrix: [supported technologies](docs/inspection/supported-technologies.md).
828
+
829
+ **Limitations.** Detection is static and evidence-based: a finding means an indicator exists, not that the project builds or runs. Frameworks seen only in a dependency declaration are marked *inferred*; imports are matched by regex, so import-like text in comments or strings can false-positive. CI, container and pre-commit detection is presence-only. Databases are inferred from driver packages. Manifests such as `Pipfile`, `setup.py`, `Cargo.toml`, `go.mod`, `Gemfile` and `pom.xml` give no dependency findings. Directories named `build`, `dist`, `env`, `target`, `vendor` and the like are skipped at any depth.
830
+
831
+ **Safety.** `spawn inspect` is read-only: it never runs repository code, installs anything, uses the network or writes to the repository, and it does not follow symbolic links. It exits 0 for complete and partial reports and 7 for an invalid path or failed inspection. See the [command reference](docs/commands.md#spawn-inspect).
796
832
 
797
833
  ### Publish to GitHub
798
834
 
@@ -825,6 +861,7 @@ All tests should pass. If they don't, please [open an issue](https://github.com/
825
861
 
826
862
  | Version | Highlight |
827
863
  |---|---|
864
+ | **v1.1.0** | `spawn inspect`: static, read-only repository inspection (languages, frameworks, dependencies, package managers, tooling, layout) with human and `--json` output; `spawn --version` |
828
865
  | **v1.0.9** | Core hardening: documented exit-code contract (generation, toolchain and publish failures exit non-zero), `--no-uv` honored for templates (file-only extras still written), path-traversal protection for custom structures, `read_project_metadata` extension boundary |
829
866
  | **v1.0.8** | `spawn doctor --fix` (`--dry-run`, `--yes`, `--license`), `--license` flag and prompt on `create`, `CHANGELOG.md` generated for every project, `pre-commit` and `mypy` extras across all templates, Custom Structure Mypy option |
830
867
  | **v1.0.7** | Fixed UTF-8 console crash on Windows when stdout is redirected/piped, added Windows reserved device name validation (`CON`, `PRN`, `AUX`, `NUL`, `COM1`–`9`, `LPT1`–`9`), clarified Python 3.12 requirement |
@@ -78,6 +78,7 @@ It's repetitive. It's inconsistent. And you haven't written a single line of *re
78
78
  | **GitHub publishing** | Connects your project to an existing GitHub repo and pushes the initial commit |
79
79
  | **spawn doctor** | Scores your project's health out of 100, with per-category breakdowns and a prioritized next step |
80
80
  | **spawn doctor --fix** | Fixes missing files and config automatically — never overwrites, never installs packages |
81
+ | **spawn inspect** | Static, read-only summary of a repository: languages, frameworks, dependencies, package managers, tooling and layout, as text or JSON |
81
82
 
82
83
  ---
83
84
 
@@ -133,12 +134,13 @@ Running `spawn` with no arguments shows the banner, the installed version, and t
133
134
 
134
135
  ```
135
136
  SPAWN — scaffold your next project
136
- v1.0.9
137
+ v1.1.0
137
138
 
138
139
  Commands
139
140
  create Scaffold a new project
140
141
  doctor Check the health of a project directory
141
142
  version Show the installed version
143
+ inspect Inspect a repository (read-only)
142
144
 
143
145
  Run spawn COMMAND --help for details on a command.
144
146
  ```
@@ -780,8 +782,42 @@ spawn doctor --fix --license mit
780
782
 
781
783
  ```bash
782
784
  spawn version
783
- # → Spawn v1.0.9
785
+ # → Spawn v1.1.0
786
+
787
+ spawn --version
788
+ # → Spawn v1.1.0
789
+ ```
790
+
791
+ ### `spawn inspect`
792
+
793
+ Give Spawn a repository and receive a deterministic, evidence-backed summary of what it contains.
794
+
795
+ ```bash
796
+ spawn inspect . # human-readable summary
797
+ spawn inspect . --json # full report on stdout, schema_version "1.0"
798
+ spawn inspect . --verbose # all dependencies, entries and evidence paths
799
+ ```
800
+
784
801
  ```
802
+ ⚡ SPAWN / INSPECT
803
+
804
+ demo
805
+ python project · 11 files · 3 directories
806
+
807
+ PROJECT OVERVIEW
808
+ Primary language python
809
+ Framework Not detected
810
+ Package manager Not detected
811
+ Origin spawn
812
+
813
+ ✓ Inspection complete
814
+ ```
815
+
816
+ **Scope.** 25 languages by extension and manifest; React, Next.js, Vue, Nuxt, Angular, Svelte, Express, FastAPI, Flask, Django, Starlette, Pydantic and Laravel; dependencies from `pyproject.toml`, `requirements*.txt` and `package.json`; package managers (uv, poetry, pipenv, pip, npm, yarn, pnpm, bun); tooling (ruff, black, flake8, mypy, pyright, pytest, eslint, prettier, jest, vitest, pre-commit, git), CI, containers and databases. Full matrix: [supported technologies](docs/inspection/supported-technologies.md).
817
+
818
+ **Limitations.** Detection is static and evidence-based: a finding means an indicator exists, not that the project builds or runs. Frameworks seen only in a dependency declaration are marked *inferred*; imports are matched by regex, so import-like text in comments or strings can false-positive. CI, container and pre-commit detection is presence-only. Databases are inferred from driver packages. Manifests such as `Pipfile`, `setup.py`, `Cargo.toml`, `go.mod`, `Gemfile` and `pom.xml` give no dependency findings. Directories named `build`, `dist`, `env`, `target`, `vendor` and the like are skipped at any depth.
819
+
820
+ **Safety.** `spawn inspect` is read-only: it never runs repository code, installs anything, uses the network or writes to the repository, and it does not follow symbolic links. It exits 0 for complete and partial reports and 7 for an invalid path or failed inspection. See the [command reference](docs/commands.md#spawn-inspect).
785
821
 
786
822
  ### Publish to GitHub
787
823
 
@@ -814,6 +850,7 @@ All tests should pass. If they don't, please [open an issue](https://github.com/
814
850
 
815
851
  | Version | Highlight |
816
852
  |---|---|
853
+ | **v1.1.0** | `spawn inspect`: static, read-only repository inspection (languages, frameworks, dependencies, package managers, tooling, layout) with human and `--json` output; `spawn --version` |
817
854
  | **v1.0.9** | Core hardening: documented exit-code contract (generation, toolchain and publish failures exit non-zero), `--no-uv` honored for templates (file-only extras still written), path-traversal protection for custom structures, `read_project_metadata` extension boundary |
818
855
  | **v1.0.8** | `spawn doctor --fix` (`--dry-run`, `--yes`, `--license`), `--license` flag and prompt on `create`, `CHANGELOG.md` generated for every project, `pre-commit` and `mypy` extras across all templates, Custom Structure Mypy option |
819
856
  | **v1.0.7** | Fixed UTF-8 console crash on Windows when stdout is redirected/piped, added Windows reserved device name validation (`CON`, `PRN`, `AUX`, `NUL`, `COM1`–`9`, `LPT1`–`9`), clarified Python 3.12 requirement |
@@ -23,9 +23,10 @@ Entry point: `spawn.cli.app:main` (defined in `pyproject.toml` as `[project.scri
23
23
 
24
24
  ```
25
25
  src/spawn/
26
- ├── __init__.py # __version__ via importlib.metadata, fallback "1.0.9"
26
+ ├── __init__.py # __version__ via importlib.metadata, fallback "1.1.0" (keep in sync with pyproject.toml)
27
27
  ├── cli/
28
- │ ├── app.py # Typer app: create, version, doctor commands
28
+ │ ├── app.py # Typer app: create, version (and --version), doctor, inspect commands
29
+ │ ├── inspect_render.py # Rich rendering of an InspectionReport for `spawn inspect`
29
30
  │ ├── noninteractive.py # Build config from CLI flags or JSON config file
30
31
  │ └── prompts.py # Interactive prompts; derives menu from registry
31
32
  ├── core/
@@ -41,6 +42,18 @@ src/spawn/
41
42
  │ ├── exceptions.py # GitHubPublishError
42
43
  │ ├── publisher.py # GitHubPublisher — stages, commits, pushes
43
44
  │ └── validators.py # GitHub URL validation
45
+ ├── inspection/ # Read-only repository inspection (never imports spawn.cli)
46
+ │ ├── models.py # Report/finding/evidence/diagnostic models, SCHEMA_VERSION, validate_report
47
+ │ ├── base.py # Analyzer protocol
48
+ │ ├── discovery.py # validate_inspection_root, discover_repository (single inventory scan)
49
+ │ ├── languages.py # LanguageDetector
50
+ │ ├── frameworks.py # FrameworkDetector
51
+ │ ├── dependencies.py # DependencyAnalyzer (dependencies, package managers)
52
+ │ ├── tooling.py # ToolingAnalyzer (tools, CI, containers, databases, structure)
53
+ │ ├── orchestrator.py # run_inspection: runs analyzers, aggregates, builds the report
54
+ │ ├── serialization.py # to_json / from_json
55
+ │ ├── exceptions.py # InspectionError (exit code 7)
56
+ │ └── _reading.py # Bounded file reads
44
57
  ├── templates/
45
58
  │ ├── base.py # BaseTemplate dataclass
46
59
  │ ├── shared_content.py # README_CONTENT, GITIGNORE_CONTENT, CI, and tool configs
@@ -255,3 +268,23 @@ To add a template: subclass `BaseTemplate` in `templates/<slug>/` and add a `Tem
255
268
  ## 10. Error model
256
269
 
257
270
  All Spawn errors derive from `SpawnError` (`core/exceptions.py`); each class carries the CLI `exit_code`. The CLI prints `❌ message` and exits with that code. See [Exit codes](commands.md#exit-codes).
271
+
272
+ ## 11. Inspection pipeline
273
+
274
+ ```
275
+ spawn inspect -> run_inspection -> validate root -> discover once -> analyzers -> aggregate/dedupe/sort -> InspectionReport -> human or JSON
276
+ ```
277
+
278
+ | Step | Owner |
279
+ |---|---|
280
+ | CLI: argument, `--json`, exit codes | `cli/app.py::inspect_command` |
281
+ | Validate root (bad root raises `InspectionError`, exit 7) | `inspection/discovery.py::validate_inspection_root` |
282
+ | Discover once: sorted files, directories, skipped, diagnostics; symlinks never followed | `inspection/discovery.py::discover_repository` |
283
+ | Analyzers, fixed order: language, framework, dependency, tooling; each gets the same immutable inventory | `inspection/orchestrator.py::ANALYZERS` |
284
+ | Isolate: a crashing or invalid analyzer becomes a `failed` result, others continue | `orchestrator._run_one` |
285
+ | Aggregate: validate findings, merge by `(category, subject)`, sort; derive summary and structure | `orchestrator._aggregate`, `_summary` |
286
+ | Render: Rich output, or `to_json` on stdout | `cli/inspect_render.py`, `inspection/serialization.py` |
287
+
288
+ Analyzers only consume the inventory (plus bounded reads of files it lists); they do not walk the tree. Nothing is executed, installed, fetched or written. `.spawn/meta.json` is read at most once, as untrusted recorded metadata.
289
+
290
+ **Module boundary:** `inspection/` never imports `spawn.cli`; `tests/test_boundaries.py` enforces this. Statuses and semantics are in [the inspection contract](inspection/inspection-contract.md); what is detected is in [supported technologies](inspection/supported-technologies.md).
@@ -3,6 +3,33 @@
3
3
  All notable changes to Spawn are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
+ ## v1.1.0 — 2026
7
+
8
+ ### Added
9
+
10
+ - **`spawn inspect [PATH] [--json] [--verbose]`** — read-only, static inspection of a repository. Prints a human summary (overview, technology, tooling, structure, diagnostics) or, with `--json`, the full report on stdout. Exits 0 for complete and partial reports and 7 for an invalid path or failed inspection (see `docs/commands.md`).
11
+ - **`spawn --version`** — prints the same line as `spawn version`.
12
+ - **Inspection contract** — `spawn.inspection` models (`InspectionReport`, `Finding`, `Evidence`, `Diagnostic`), `SCHEMA_VERSION` `"1.0"`, `validate_report`, and `to_json` / `from_json`. See `docs/inspection/inspection-contract.md`.
13
+ - **Safe discovery** — one sorted inventory scan; symlinks and junctions are never followed, default exclusions (`.git`, `node_modules`, `build`, `dist`, `venv`, `env`, `target`, ...) match at any depth, errors below the root become diagnostics.
14
+ - **Language and framework detection** — 25 languages by extension and manifest; React, Next.js, Vue, Nuxt, Angular, Svelte, Express, FastAPI, Flask, Django, Starlette, Pydantic and Laravel from manifests (inferred), imports and config files (detected).
15
+ - **Dependency and package-manager analyzer** — direct dependencies from `pyproject.toml`, `requirements*.txt` and `package.json`; uv, poetry, pipenv, pip, npm, yarn, pnpm and bun.
16
+ - **Tooling analyzer** — Python and JavaScript tools, git, CI systems, Docker and Compose, database drivers, `tests-directory`, `src-layout` and `spawn-generated` markers.
17
+ - **Orchestrator** — runs the analyzers in a fixed order with per-analyzer isolation, merges findings by `(category, subject)`, derives the summary and structure, and reads `.spawn/meta.json` as untrusted recorded metadata.
18
+ - **Test corpus** — generated fixture repositories and a regression suite (`tests/test_inspection_*.py`).
19
+ - Release smoke test now runs `spawn inspect . --json` against a generated project and checks it is unchanged.
20
+
21
+ ### Known limitations
22
+
23
+ - Excluded directory basenames (`build`, `env`, `target`, `vendor`, `dist`, `coverage`, ...) match at any depth.
24
+ - `.git` is detected through discovery's skipped list only.
25
+ - Framework imports are regex-matched: import-like text in comments or strings can false-positive; multi-line and destructured imports are missed.
26
+ - Frameworks found only in a dependency declaration are inferred, and `primary_framework` may be inferred.
27
+ - CI, container and pre-commit detection is presence-only (no YAML parsing).
28
+ - Databases are inferred from driver packages only.
29
+ - A pip and an npm package with the same name share one finding.
30
+ - `Pipfile`, `setup.py`, `Cargo.toml`, `go.mod`, `Gemfile`, `composer.json`, `pom.xml` and Gradle files produce no dependency findings; Rails is not detected.
31
+ - `summary.name` is the directory basename.
32
+
6
33
  ## v1.0.9 — 2026
7
34
 
8
35
  ### Added
@@ -7,7 +7,8 @@
7
7
  | `spawn` | Show the banner, version, and command list |
8
8
  | `spawn create` | Scaffold a new project (interactive or non-interactive) |
9
9
  | `spawn doctor` | Score a project directory's health out of 135 |
10
- | `spawn version` | Print the installed version |
10
+ | `spawn inspect` | Inspect a repository and report what it contains (read-only) |
11
+ | `spawn version` | Print the installed version (also `spawn --version`) |
11
12
 
12
13
  ---
13
14
 
@@ -18,12 +19,13 @@ Running `spawn` with no arguments prints the ASCII banner, the installed version
18
19
  ```
19
20
  <ASCII SPAWN banner — "scaffold your next project">
20
21
 
21
- v1.0.9
22
+ v1.1.0
22
23
 
23
24
  Commands
24
25
  create Scaffold a new project
25
26
  doctor Check the health of a project directory
26
27
  version Show the installed version
28
+ inspect Inspect a repository (read-only)
27
29
 
28
30
  Run spawn COMMAND --help for details on a command.
29
31
  ```
@@ -398,7 +400,7 @@ If `--claude-md` was passed (or `"claude_md": true` in the config file), a `CLAU
398
400
  "intent": "backend-api",
399
401
  "framework": "fastapi",
400
402
  "provider": null,
401
- "spawn_version": "1.0.9",
403
+ "spawn_version": "1.1.0",
402
404
  "created_at": "2026-01-01T00:00:00+00:00",
403
405
  "generator": "blueprint",
404
406
  "git": true,
@@ -518,13 +520,71 @@ spawn doctor --fix --license mit
518
520
 
519
521
  ---
520
522
 
523
+ ## `spawn inspect`
524
+
525
+ ```
526
+ spawn inspect [PATH] [--json] [--verbose | -v]
527
+ ```
528
+
529
+ Statically inspects a repository and reports its languages, frameworks, declared dependencies, package managers, engineering tooling and layout. `PATH` defaults to `.`. Every positive finding carries repository-relative evidence.
530
+
531
+ | Option | Effect |
532
+ |---|---|
533
+ | `--json` | Print the full report as JSON on stdout (`schema_version` `"1.0"`); errors go to stderr |
534
+ | `--verbose`, `-v` | Show all dependencies, all top-level entries and evidence paths |
535
+
536
+ ### Safety
537
+
538
+ `spawn inspect` is read-only and static. It never executes or imports repository code, installs dependencies, uses the network or writes to the repository. Symbolic links and directory junctions are listed as skipped, never followed. Files are read with a 1 MB cap. `.env` files are never read.
539
+
540
+ ### Human output
541
+
542
+ Sections, in order: header, **Project overview** (primary language, framework, package manager, origin, Spawn version for Spawn-generated projects), **Technology** (languages, other frameworks, dependencies), **Tooling** (tools, CI, containers, databases), **Repository structure** (file/directory counts, top-level entries, structure markers), **Diagnostics**, and a final status line.
543
+
544
+ State markers:
545
+
546
+ | Marker (ASCII) | State | Meaning |
547
+ |---|---|---|
548
+ | `✓` (`+`) | detected | A direct static indicator exists |
549
+ | `~` | inferred | Indirect evidence only (for example a declared dependency without config); the detail says why |
550
+ | `?` | unknown | The check could not be completed |
551
+ | `○` (`-`) | not detected / not checked | Looked for and absent, or not looked for |
552
+
553
+ The framework line is suffixed `inferred` when the primary framework rests on a dependency declaration alone. Diagnostics list warnings and errors with a stable code (for example `discovery.permission_denied`, `framework.malformed_manifest`) and the affected path. A report with warnings ends `Inspection partial: findings may be incomplete`.
554
+
555
+ ### JSON output
556
+
557
+ `--json` writes one JSON document to stdout and nothing else. `target.root` is always `"."`; no absolute path is emitted. Fields: `schema_version`, `status`, `generated_at`, `target`, `recorded_metadata`, `summary`, `structure`, `findings`, `analyzer_results`, `diagnostics`.
558
+
559
+ ```bash
560
+ spawn inspect ./my-project --json
561
+ ```
562
+
563
+ ### Inspect exit codes
564
+
565
+ | Code | When |
566
+ |---|---|
567
+ | 0 | Inspection complete or partial (a partial report still prints) |
568
+ | 7 | Path missing, not a directory or unreadable; or the repository root could not be scanned (status `failed`) |
569
+ | 10 | Unexpected error |
570
+
571
+ With `--json`, an invalid path prints the message to stderr, leaves stdout empty and exits 7. An unexpected error in `--json` mode also prints to stderr only (`SPAWN_DEBUG=1` raises the traceback).
572
+
573
+ ### Limitations
574
+
575
+ See [Supported technologies](inspection/supported-technologies.md#limitations) for what is and is not detected.
576
+
577
+ ---
578
+
521
579
  ## `spawn version`
522
580
 
523
- Prints the installed version. No arguments or options; exit code 0; writes nothing.
581
+ Prints the installed version. `spawn --version` prints the same line. No other arguments or options; exit code 0; writes nothing.
524
582
 
525
583
  ```bash
526
584
  spawn version
527
- # Spawn v1.0.9
585
+ # Spawn v1.1.0
586
+ spawn --version
587
+ # Spawn v1.1.0
528
588
  ```
529
589
 
530
590
  ---
@@ -540,6 +600,7 @@ spawn version
540
600
  | 4 | Toolchain error (`git` or `uv` missing or failed) |
541
601
  | 5 | Generation / template error |
542
602
  | 6 | Publish error (GitHub publishing failed) |
603
+ | 7 | Inspection error (`spawn inspect`: invalid or unreadable path, or a failed inspection) |
543
604
  | 10 | Unexpected error (re-run with `SPAWN_DEBUG=1` for a traceback) |
544
605
  | 130 | Cancelled (Ctrl+C, EOF, or declining the final prompt) |
545
606
 
@@ -49,19 +49,20 @@ After installation, `spawn` is available anywhere on your machine.
49
49
 
50
50
  ```bash
51
51
  spawn version
52
- # Spawn v1.0.9
52
+ # Spawn v1.1.0
53
53
  ```
54
54
 
55
55
  Or just run `spawn` with no arguments to see the command overview:
56
56
 
57
57
  ```
58
58
  SPAWN — scaffold your next project
59
- v1.0.9
59
+ v1.1.0
60
60
 
61
61
  Commands
62
62
  create Scaffold a new project
63
63
  doctor Check the health of a project directory
64
64
  version Show the installed version
65
+ inspect Inspect a repository (read-only)
65
66
 
66
67
  Run spawn COMMAND --help for details on a command.
67
68
  ```