ssmforge 0.2.2__tar.gz → 0.2.4__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 (24) hide show
  1. {ssmforge-0.2.2/src/ssmforge.egg-info → ssmforge-0.2.4}/PKG-INFO +814 -3
  2. {ssmforge-0.2.2 → ssmforge-0.2.4}/README.md +813 -2
  3. {ssmforge-0.2.2 → ssmforge-0.2.4}/pyproject.toml +1 -1
  4. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/__init__.py +1 -1
  5. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/cli.py +177 -9
  6. {ssmforge-0.2.2 → ssmforge-0.2.4/src/ssmforge.egg-info}/PKG-INFO +814 -3
  7. {ssmforge-0.2.2 → ssmforge-0.2.4}/LICENSE +0 -0
  8. {ssmforge-0.2.2 → ssmforge-0.2.4}/MANIFEST.in +0 -0
  9. {ssmforge-0.2.2 → ssmforge-0.2.4}/docs/DEPLOY.md +0 -0
  10. {ssmforge-0.2.2 → ssmforge-0.2.4}/docs/INSTALL.md +0 -0
  11. {ssmforge-0.2.2 → ssmforge-0.2.4}/docs/quickstart.md +0 -0
  12. {ssmforge-0.2.2 → ssmforge-0.2.4}/setup.cfg +0 -0
  13. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/__init__.py +0 -0
  14. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/diff.py +0 -0
  15. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/graph.py +0 -0
  16. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/markdown_render.py +0 -0
  17. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/report.py +0 -0
  18. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/state_dict_scan.py +0 -0
  19. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge/analyze/summary.py +0 -0
  20. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge.egg-info/SOURCES.txt +0 -0
  21. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge.egg-info/dependency_links.txt +0 -0
  22. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge.egg-info/entry_points.txt +0 -0
  23. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge.egg-info/requires.txt +0 -0
  24. {ssmforge-0.2.2 → ssmforge-0.2.4}/src/ssmforge.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssmforge
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Standalone HF architecture analyzer (`ssmforge arch`). Inspects any HuggingFace model and reports architectural quirks — attention biases, fused QKV/gate-up, tied embeddings, GQA, MQA, MoE, sliding window, LayerScale, soft-capping, partial RoPE, MLP type, norm type. Outputs structured JSON + human-readable summary.
5
5
  Author: SSMForge Contributors
6
6
  License-Expression: Apache-2.0
@@ -60,6 +60,16 @@ ssmforge arch Qwen/Qwen2-1.5B-Instruct
60
60
  14. [Why this exists](#14-why-this-exists)
61
61
  15. [Limitations](#15-limitations)
62
62
  16. [Update log](#16-update-log)
63
+ 17. [Comprehensive Usage Guide](#17-comprehensive-usage-guide)
64
+ - 17.1 [Decision tree](#171-decision-tree-which-command-do-i-want)
65
+ - 17.2 [Every arch flag](#172-every-arch-flag-what-it-does-when-to-use-it)
66
+ - 17.3 [Every doctor flag](#173-every-doctor-flag)
67
+ - 17.4 [Output format decision guide](#174-output-format-decision-guide)
68
+ - 17.5 [Real-world workflows](#175-real-world-workflows)
69
+ - 17.6 [Web interfaces (PyPI + GitHub)](#176-web-interfaces-what-users-see)
70
+ - 17.7 [Batch processing](#177-batch-processing-file-by-file-loops)
71
+ - 17.8 [Troubleshooting cookbook](#178-troubleshooting-cookbook)
72
+ - 17.9 [Recipe index](#179-recipe-index-quick-lookup)
63
73
 
64
74
  ---
65
75
 
@@ -82,6 +92,37 @@ visible *before* you spend the next hour finding out the hard way.
82
92
  It does **not** modify the model. It does **not** run inference. It only
83
93
  inspects.
84
94
 
95
+ ### What's new in 0.2.4
96
+
97
+ | Area | What's added |
98
+ |------|--------------|
99
+ | **Comprehensive Usage Guide (§17)** | 9-section deep dive covering every flag, every command, every workflow. Includes decision tree, output-format picker, 7 real-world workflows (CI/CD, batch processing, model selection), web interface tour (PyPI + GitHub), troubleshooting cookbook, recipe index. |
100
+ | **Web interface section** | Explains what users see on PyPI and GitHub, how the README becomes the canonical doc, how to set up repo Settings (Issues, Discussions) so users can file bugs and ask questions. |
101
+
102
+ Pure documentation release — no behavior changes, no new tests, no PyPI surprises. Just deeper, more useful docs.
103
+
104
+ ### What's new in 0.2.3
105
+
106
+ | Fix | What was broken |
107
+ |-----|-----------------|
108
+ | `--output` on Git Bash + Windows with unquoted backslash paths | Git Bash strips backslashes from unquoted args, so `--output C:\Users\foo\out.md` reached Python as `C:Usersfooout.md` — silently writing a single literal-named file in the cwd. Pre-parse guard now catches this BEFORE argparse runs and exits 1 with a clear "wrap in double quotes or use forward slashes" hint. |
109
+ | `C:Usersnetge...` (bash-mangled, no separators) detected | The post-write `_check_output_path` was too late. The pre-parse guard catches the mangled pattern early and tells you exactly what bash did to your argument. |
110
+
111
+ **Quote your paths from now on.** Or use forward slashes — they work on both Windows and POSIX.
112
+
113
+ ```bash
114
+ # ✅ Recommended — works everywhere
115
+ python -m ssmforge.cli arch X --graph --format markdown --output ~/Desktop/report.md
116
+ python -m ssmforge.cli arch X --graph --format markdown --output ./report.md
117
+ python -m ssmforge.cli arch X --graph --format markdown --output "C:/Users/me/Desktop/report.md"
118
+
119
+ # ❌ These will now fail with a clear error:
120
+ python -m ssmforge.cli arch X --graph --format markdown --output C:\Users\me\Desktop\report.md
121
+ python -m ssmforge.cli arch X --graph --format markdown --output C:UsersmeDesktopreport.md
122
+ ```
123
+
124
+ Plus 9 new tests (174 total).
125
+
85
126
  ### What's new in 0.2.2
86
127
 
87
128
  | Fix | What was broken |
@@ -1400,7 +1441,82 @@ install.
1400
1441
 
1401
1442
  ## 16. Update log
1402
1443
 
1403
- ### v0.2.2 (current) — 2026-09-23
1444
+ ### v0.2.4 (current) — 2026-09-23
1445
+
1446
+ **Documentation: Comprehensive Usage Guide (§17)**
1447
+
1448
+ Added a 9-section, 700+ line deep dive into how to actually use ssmforge:
1449
+
1450
+ - **17.1 Decision tree** — "What do you want to do?" → which command
1451
+ - **17.2 Every `arch` flag** — what each flag does, when to use it,
1452
+ with multiple examples per flag
1453
+ - **17.3 Every `doctor` flag** — `doctor` + `--check-install`
1454
+ - **17.4 Output format decision guide** — table mapping "what you
1455
+ want" → "which format"
1456
+ - **17.5 Real-world workflows** — 7 end-to-end recipes (model
1457
+ evaluation, model selection, batch processing for benchmarks,
1458
+ CI/CD, docs generation, VRAM filtering, bug report prep)
1459
+ - **17.6 Web interface tour** — what users see on PyPI and GitHub,
1460
+ how README becomes the canonical doc, repo Settings checklist
1461
+ - **17.7 Batch processing** — shell and Python patterns for
1462
+ iterating over many models
1463
+ - **17.8 Troubleshooting cookbook** — common error → one-line fix
1464
+ - **17.9 Recipe index** — copy-paste recipes for common queries
1465
+
1466
+ This is a docs-only release. No code changes. Tests still at 174
1467
+ passing. 32 anchor links verified (0 broken), 0 platform refs.
1468
+
1469
+ ### v0.2.3 — 2026-09-23
1470
+
1471
+ ### v0.2.3 (current) — 2026-09-23
1472
+
1473
+ **Bug fix: Git Bash strips backslashes from unquoted `--output` args**
1474
+
1475
+ When you run on Git Bash + Windows and pass an unquoted Windows path:
1476
+ ```bash
1477
+ python -m ssmforge.cli arch X --graph --format markdown \
1478
+ --output C:\Users\netge\Desktop\report.md
1479
+ ```
1480
+
1481
+ Git Bash sees the backslashes as path separators and strips them
1482
+ **before** passing the argument to Python. Python receives:
1483
+ ```
1484
+ --output C:UsersnetgeDesktopreport.md
1485
+ ```
1486
+ which is interpreted as a single literal filename containing no
1487
+ separators. The CLI then writes a file named
1488
+ `./C:UsersnetgeDesktopreport.md` in the current directory — totally
1489
+ wrong, and v0.2.2 didn't catch it.
1490
+
1491
+ **v0.2.3 fixes this with a pre-parse guard** that runs before argparse
1492
+ and checks for:
1493
+
1494
+ 1. **Literal backslash paths** (`C:\\file.md`) — caught with hint to
1495
+ use forward slashes or wrap in quotes.
1496
+ 2. **Bash-mangled paths** (`C:UsersnetgeDesktop.md`) — caught with
1497
+ hint explaining what bash did to the argument.
1498
+
1499
+ The error fires immediately, before any model is loaded:
1500
+
1501
+ ```
1502
+ Error: --output value looks like a bash-mangled Windows path.
1503
+ Got: 'C:UsersnetgeDesktopreport.md'
1504
+ Git Bash strips backslashes from unquoted arguments.
1505
+ Wrap the value in double quotes, e.g.:
1506
+ --output "C:\Users\netge\Desktop\report.md"
1507
+ Or use forward slashes (works on both Windows and POSIX):
1508
+ --output C:/Users/netge/Desktop/report.md
1509
+ ```
1510
+
1511
+ **Recommended from v0.2.3 onward:** quote all `--output` paths, or
1512
+ use forward slashes.
1513
+
1514
+ Tests: 174 passed (was 165). 9 new tests for the pre-parse guard
1515
+ covering bash-mangled separate-args, bash-mangled equals-form,
1516
+ backslash-only paths, plain POSIX paths, forward-slash Windows paths,
1517
+ and bare drive-letter patterns.
1518
+
1519
+ ### v0.2.2 — 2026-09-23
1404
1520
 
1405
1521
  **Bug fix: `--output PATH` directory validation**
1406
1522
 
@@ -1756,7 +1872,702 @@ pip install ssmforge
1756
1872
 
1757
1873
  ---
1758
1874
 
1759
- ## Contributing
1875
+ ## 17. Comprehensive Usage Guide
1876
+
1877
+ This is the deep-dive section — every flag combination, every workflow,
1878
+ every way users actually use ssmforge in real life. Skim if you know what
1879
+ you want, read it through if you're new.
1880
+
1881
+ ### 17.1 Decision tree — "Which command do I want?"
1882
+
1883
+ ```
1884
+ Want to...
1885
+ ├── Inspect ONE model?
1886
+ │ ├── Without downloading weights → arch X --dry-run
1887
+ │ ├── With weights (full scan) → arch X
1888
+ │ ├── Just the profile summary → arch X --profile
1889
+ │ ├── Visual decision graph (terminal) → arch X --graph
1890
+ │ ├── JSON for a script → arch X --quiet --format json
1891
+ │ ├── Markdown for a GitHub Issue → arch X --quiet --format markdown --output issue.md
1892
+ │ ├── Save JSON to a file → arch X --output report.json
1893
+ │ ├── Subset to specific fields → arch X --fields quirks
1894
+ │ ├── Pin to a specific HF commit → arch X --rev v2.3 --dry-run
1895
+ │ └── Load a local model from disk → arch /path/to/model --dry-run
1896
+ │
1897
+ ├── Compare 2+ models?
1898
+ │ ├── 2 models, JSON diff (legacy) → arch A --diff B
1899
+ │ ├── 2+ models, side-by-side table → arch --compare A B
1900
+ │ ├── 2+ models, source + compare list → arch A --compare B C D
1901
+ │ ├── Show only the things that differ → arch --compare A B C --only-different
1902
+ │ ├── Just their profiles → arch --compare A B --profile
1903
+ │ ├── Decision graph (text/json/markdown) → arch --compare A B C --graph --format markdown
1904
+ │ └── Subset to specific fields → arch --compare A B --fields profile
1905
+ │
1906
+ ├── Diagnose my install?
1907
+ │ ├── Full environment info → doctor
1908
+ │ ├── Install checks (PATH, scripts) → doctor --check-install
1909
+ │ └── Machine-readable → doctor --check-install --format json
1910
+ │
1911
+ └── Use as a Python library?
1912
+ ├── Detect quirks from a config → from ssmforge.analyze import scan_config_only
1913
+ ├── Detect quirks from a state dict → from ssmforge.analyze import scan_state_dict
1914
+ ├── Build a full report → from ssmforge.analyze import build_report_from_config
1915
+ ├── Compare two reports → from ssmforge.analyze import compare_reports
1916
+ └── Render a graph → from ssmforge.analyze import render_graph_text
1917
+ ```
1918
+
1919
+ ### 17.2 Every `arch` flag — what it does, when to use it
1920
+
1921
+ Single-model inspection. Source can be an HF id or a local path.
1922
+
1923
+ #### `--output PATH` / `-o PATH`
1924
+
1925
+ Where the report lands. If omitted, the report goes to stdout (so you can
1926
+ pipe to `jq`, `less`, etc.). Use `-` to be explicit about stdout. Use a
1927
+ quoted absolute path when going to a directory other than cwd.
1928
+
1929
+ ```bash
1930
+ # stdout (default, pipe-friendly)
1931
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run
1932
+
1933
+ # write to a file in cwd
1934
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --output qwen2.json
1935
+
1936
+ # write to a specific directory (wrap path in quotes on Windows)
1937
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --output "~/Desktop/qwen2.md"
1938
+
1939
+ # explicit stdout
1940
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --output -
1941
+ ```
1942
+
1943
+ See **17.8 Troubleshooting** if you see `Permission denied` on `--output`.
1944
+
1945
+ #### `--format {text,json,markdown,md}` / `-f FORMAT`
1946
+
1947
+ What shape the output takes.
1948
+
1949
+ | Format | When to use |
1950
+ |--------|-------------|
1951
+ | `text` (default for `--graph`) | Terminal viewing — human reads it |
1952
+ | `json` (default for `arch`) | Pipelines — `jq`, scripts, comparison tools |
1953
+ | `markdown` / `md` | Documentation — paste into GitHub, Obsidian, Notion |
1954
+ | `text` for `--graph` | Box-drawing in your terminal |
1955
+
1956
+ ```bash
1957
+ # JSON, the default — machine-friendly
1958
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run
1959
+
1960
+ # Markdown for a docs page
1961
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --format markdown --output doc.md
1962
+
1963
+ # Text graph in the terminal
1964
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --graph --format text
1965
+
1966
+ # JSON for a script
1967
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --quiet | python -m json.tool > pretty.json
1968
+ ```
1969
+
1970
+ #### `--quiet`
1971
+
1972
+ Suppress the human-readable summary that ssmforge normally prints to
1973
+ stderr. Use this when you're piping to a tool that doesn't want the
1974
+ extra noise.
1975
+
1976
+ ```bash
1977
+ # With --quiet: just the JSON, nothing else
1978
+ ssmforge arch X --dry-run --quiet | jq '.quirks'
1979
+
1980
+ # Without --quiet: JSON + human summary on stderr
1981
+ ssmforge arch X --dry-run | jq '.quirks'
1982
+ ```
1983
+
1984
+ #### `--diff OTHER_MODEL`
1985
+
1986
+ Compare against one other model. Loads both, prints a JSON diff.
1987
+ Two-model legacy interface — prefer `--compare` for 2+ models.
1988
+
1989
+ ```bash
1990
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --diff TinyLlama/TinyLlama-1.1B-Chat-v1.0
1991
+ ```
1992
+
1993
+ #### `--compare MODEL [MODEL ...]`
1994
+
1995
+ Side-by-side comparison of 2+ models. The first model can come from the
1996
+ positional `source` argument; the rest from `--compare`. Output is a
1997
+ table showing each model's value for each field.
1998
+
1999
+ ```bash
2000
+ # All from --compare
2001
+ ssmforge arch --compare TinyLlama-1.1B Qwen2-0.5B Qwen2-1.5B --dry-run
2002
+
2003
+ # Positional + --compare
2004
+ ssmforge arch TinyLlama-1.1B --compare Qwen2-0.5B Qwen2-1.5B --dry-run
2005
+
2006
+ # Mixed: positional then --compare
2007
+ ssmforge arch Qwen2-0.5B Qwen2-1.5B Phi-2-moe --dry-run
2008
+
2009
+ # Same model twice (e.g., "compare A against itself")
2010
+ ssmforge arch --compare Qwen2-0.5B Qwen2-0.5B --dry-run # → all_identical=True
2011
+ ```
2012
+
2013
+ #### `--dry-run`
2014
+
2015
+ Fetch only the config, skip the GB download. Estimates memory from the
2016
+ config alone. Quirks that require actual weight inspection will be
2017
+ marked `unknown` with a note.
2018
+
2019
+ ```bash
2020
+ ssmforge arch bigscience/bloom-7b1 --dry-run # 0 MB downloaded
2021
+ ssmforge arch bigscience/bloom-7b1 # ~13 GB downloaded
2022
+ ```
2023
+
2024
+ Always use `--dry-run` for unfamiliar models first.
2025
+
2026
+ #### `--rev REVISION` / `--revision REVISION`
2027
+
2028
+ Pin to a specific HF commit, tag, or branch instead of HEAD. Critical
2029
+ for reproducibility — without this, the report changes whenever the
2030
+ upstream model gets a new commit.
2031
+
2032
+ ```bash
2033
+ ssmforge arch TinyLlama/TinyLlama-1.1B-Chat-v1.0 --rev v1.0
2034
+ ssmforge arch TinyLlama/TinyLlama-1.1B-Chat-v1.0 --rev ecfab3a # full sha
2035
+ ssmforge arch TinyLlama/TinyLlama-1.1B-Chat-v1.0 --rev main # branch
2036
+ ```
2037
+
2038
+ The resolved revision sha is stamped on the report as `hf_revision`.
2039
+
2040
+ #### `--fields NAME1,NAME2`
2041
+
2042
+ Subset the output to only the requested fields. Works for both single
2043
+ and `--compare` mode. Dotted paths supported.
2044
+
2045
+ ```bash
2046
+ # Single model: only the quirks section
2047
+ ssmforge arch X --dry-run --fields quirks
2048
+
2049
+ # Single model: a specific quirk via dotted path
2050
+ ssmforge arch X --dry-run --fields "quirks.attention_bias,profile.family"
2051
+
2052
+ # All quirks + the family
2053
+ ssmforge arch X --dry-run --fields "quirks,profile.family"
2054
+
2055
+ # Compare: only the geometry table fields
2056
+ ssmforge arch --compare A B C --dry-run --fields "hidden_size,num_hidden_layers"
2057
+ ```
2058
+
2059
+ #### `--only-different`
2060
+
2061
+ Compare mode only. Hide the "Identical across all models" footer.
2062
+ Pairs naturally with `--compare`.
2063
+
2064
+ ```bash
2065
+ ssmforge arch --compare TinyLlama-1.1B Qwen2-0.5B Qwen2-1.5B --dry-run --only-different
2066
+ ```
2067
+
2068
+ #### `--profile`
2069
+
2070
+ Emit just the profile section (family, attention_type, mlp_type,
2071
+ norm_type, descriptors). Useful for "what kind of model is this at
2072
+ a glance" check.
2073
+
2074
+ ```bash
2075
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --profile
2076
+ # → {"model_id": "...", "profile": {...}}
2077
+ ```
2078
+
2079
+ #### `--graph`
2080
+
2081
+ Render a text-based architecture decision graph. Honors `--format`:
2082
+
2083
+ - `--format text` — ASCII box-drawing, default for `--graph`
2084
+ - `--format json` — structured pipeline + decisions
2085
+ - `--format markdown` — GFM tables for docs
2086
+
2087
+ ```bash
2088
+ # ASCII graph in terminal
2089
+ ssmforge arch X --graph --format text
2090
+
2091
+ # JSON graph for piping
2092
+ ssmforge arch X --graph --format json | jq .pipeline
2093
+
2094
+ # Markdown graph for docs
2095
+ ssmforge arch X --graph --format markdown --output graph.md
2096
+
2097
+ # Compare as a graph (3 formats)
2098
+ ssmforge arch --compare A B C --dry-run --graph --format markdown
2099
+ ```
2100
+
2101
+ The graph renders the dataflow: input → embed → layer_block →
2102
+ final_norm → logits, with each architectural choice (fused QKV,
2103
+ GQA, attention_bias, MLP type, MoE, tied embeddings) marked with
2104
+ its verdict right where it matters in the pipeline.
2105
+
2106
+ ### 17.3 Every `doctor` flag
2107
+
2108
+ #### `doctor` (no flag)
2109
+
2110
+ Print full environment info: ssmforge version, Python version, HF_HOME,
2111
+ HF token status, transformers version, huggingface_hub version.
2112
+
2113
+ ```bash
2114
+ ssmforge doctor
2115
+ # ssmforge doctor
2116
+ # ----------------------------------------
2117
+ # ssmforge_version: 0.2.3
2118
+ # python_version: 3.14.4
2119
+ # platform: win32
2120
+ # hf_home: G:/models
2121
+ # ...
2122
+
2123
+ ssmforge doctor --format json | jq .transformers_version
2124
+ ```
2125
+
2126
+ Use this when filing a bug report — paste the output.
2127
+
2128
+ #### `doctor --check-install`
2129
+
2130
+ Diagnose install issues. Exits non-zero on problems. Use this to verify
2131
+ your install before opening an issue.
2132
+
2133
+ ```bash
2134
+ ssmforge doctor --check-install
2135
+ # ssmforge doctor --check-install (0.2.3)
2136
+ # --------------------------------------------------
2137
+ # ✓ ssmforge command on PATH: True
2138
+ # python: C:\Users\netge\.venv\Scripts\python.exe
2139
+ # platform: win32
2140
+ ```
2141
+
2142
+ When something is wrong:
2143
+
2144
+ ```
2145
+ ssmforge doctor --check-install
2146
+ # ✗ ssmforge command on PATH: False
2147
+ # python: C:\Python314\python.exe
2148
+ # platform: win32
2149
+ #
2150
+ # The 'ssmforge' script was installed to:
2151
+ # C:\Users\netge\AppData\Roaming\Python\Python314\Scripts\ssmforge.exe
2152
+ # but that folder is not on PATH.
2153
+ #
2154
+ # Quick fix (current shell):
2155
+ # export PATH="/c/Users/netge/AppData/Roaming/Python/Python314/Scripts:$PATH"
2156
+ # Permanent fix (PowerShell, restart shell after):
2157
+ # [Environment]::SetEnvironmentVariable("PATH", ...)
2158
+ # Or just use: python -m ssmforge.cli
2159
+ exit=$? # 1
2160
+ ```
2161
+
2162
+ Use `--format json` for scripts:
2163
+
2164
+ ```bash
2165
+ ssmforge doctor --check-install --format json | jq '.ssmforge_command_on_path'
2166
+ # → true / false
2167
+ ```
2168
+
2169
+ ### 17.4 Output format decision guide
2170
+
2171
+ What format should I use? Follow this:
2172
+
2173
+ | Goal | Format | Why |
2174
+ |------|--------|-----|
2175
+ | Read in a terminal | `text` | No markup noise |
2176
+ | Pipe to `jq` / grep | `json` | Structured, line-stable |
2177
+ | Save as artifact | `json` | Round-trippable for later tools |
2178
+ | Paste into GitHub Issue | `markdown` | Renders as a real table |
2179
+ | Send to a doc writer | `markdown` | No escaping needed |
2180
+ | Generate a visualization | `json` | Re-arrangeable structured data |
2181
+ | Compare 2 models in a doc | `markdown --compare` | Side-by-side table |
2182
+ | Show arch decisions in a meeting | `text --graph` | Box-drawing, no scroll |
2183
+ | Pipe into another tool | `json` | Don't fight the format battle |
2184
+
2185
+ ### 17.5 Real-world workflows
2186
+
2187
+ #### Workflow 1: "I'm thinking of fine-tuning a model — what's it look like?"
2188
+
2189
+ ```bash
2190
+ # 1. Quick profile (no download)
2191
+ ssmforge arch Qwen/Qwen2-7B-Instruct --dry-run --profile | jq .profile
2192
+
2193
+ # 2. Full quirk scan if it looks plausible (still no download)
2194
+ ssmforge arch Qwen/Qwen2-7B-Instruct --dry-run --quiet | jq '.quirks'
2195
+
2196
+ # 3. If you commit to it, pull the actual weights
2197
+ ssmforge arch Qwen/Qwen2-7B-Instruct # ~14 GB
2198
+ ```
2199
+
2200
+ #### Workflow 2: "I want to pick between two models for production"
2201
+
2202
+ ```bash
2203
+ # 1. Side-by-side (config-only)
2204
+ ssmforge arch --compare TinyLlama-1.1B-Chat Qwen2-1.5B-Instruct --dry-run --only-different
2205
+
2206
+ # 2. Markdown for the architecture-review doc
2207
+ ssmforge arch --compare A B C --dry-run --format markdown --output model-review.md
2208
+
2209
+ # 3. JSON for the deployment script
2210
+ ssmforge arch --compare A B C --dry-run --quiet --format json --output comparison.json
2211
+ ```
2212
+
2213
+ #### Workflow 3: "Generate a benchmark dataset of arch profiles"
2214
+
2215
+ ```bash
2216
+ #!/bin/bash
2217
+ # batch_inspect.sh — generate JSON for every model in a list
2218
+ MODELS="Qwen/Qwen2-0.5B Qwen/Qwen2-1.5B TinyLlama/TinyLlama-1.1B-Chat-v1.0 microsoft/Phi-2"
2219
+ mkdir -p profiles/
2220
+
2221
+ for model in $MODELS; do
2222
+ safe=$(echo "$model" | tr '/' '_')
2223
+ ssmforge arch "$model" --dry-run --quiet --format json --output "profiles/${safe}.json"
2224
+ done
2225
+
2226
+ # Concatenate into a single CSV-like view
2227
+ for f in profiles/*.json; do
2228
+ jq -r '"\(.model_id)\t\(.profile.family)\t\(.memory_estimate.estimated_params)"' "$f"
2229
+ done > summary.tsv
2230
+ ```
2231
+
2232
+ #### Workflow 4: "Pre-flight in CI/CD — fail the build if the model is incompatible"
2233
+
2234
+ ```yaml
2235
+ # .github/workflows/check-model.yml
2236
+ name: Check model compatibility
2237
+ on: [push]
2238
+ jobs:
2239
+ check:
2240
+ runs-on: ubuntu-latest
2241
+ steps:
2242
+ - uses: actions/checkout@v4
2243
+ - run: pip install ssmforge
2244
+ - name: Check target model is compatible
2245
+ run: |
2246
+ # Exit 1 if model has any compatibility blockers
2247
+ ssmforge arch ${{ env.MODEL }} --dry-run --quiet > profile.json
2248
+ python -c "
2249
+ import json, sys
2250
+ profile = json.load(open('profile.json'))
2251
+ if not profile['compatibility']['is_compatible']:
2252
+ print('BLOCKERS:', profile['compatibility']['blockers'])
2253
+ sys.exit(1)
2254
+ "
2255
+ ```
2256
+
2257
+ #### Workflow 5: "Generate a README.md section for every supported model"
2258
+
2259
+ ```bash
2260
+ #!/bin/bash
2261
+ # gen_docs.sh — produce markdown descriptions for a list of models
2262
+ MODELS=$(cat supported-models.txt)
2263
+
2264
+ for model in $MODELS; do
2265
+ safe=$(echo "$model" | tr '/' '_')
2266
+ ssmforge arch "$model" --dry-run --graph --format markdown --output "docs/models/${safe}.md"
2267
+ done
2268
+ ```
2269
+
2270
+ Each `*.md` file can be pasted directly into a docs site, GitHub Wiki,
2271
+ or knowledge base — full Markdown tables, decisions in bold, geometry
2272
+ in a header. Ready for human consumption.
2273
+
2274
+ #### Workflow 6: "Find models that fit a 12 GB GPU"
2275
+
2276
+ ```bash
2277
+ #!/usr/bin/env python
2278
+ # fit_to_vram.py — filter a model list by VRAM budget
2279
+ import json, subprocess
2280
+ MODELS = ["Qwen/Qwen2-0.5B-Instruct", "Qwen/Qwen2-1.5B-Instruct",
2281
+ "Qwen/Qwen2-7B-Instruct", "Qwen/Qwen2-72B-Instruct"]
2282
+ BUDGET_GB = 12
2283
+
2284
+ for model in MODELS:
2285
+ result = subprocess.run(
2286
+ ["ssmforge", "arch", model, "--dry-run", "--quiet", "--fields", "memory"],
2287
+ capture_output=True, text=True,
2288
+ )
2289
+ if result.returncode != 0:
2290
+ print(f"{model}: ERROR ({result.stderr.strip()})")
2291
+ continue
2292
+ profile = json.loads(result.stdout)
2293
+ mem_bf16 = profile["memory_estimate"]["estimated_bytes"] / (1 << 30)
2294
+ mem_int8 = mem_bf16 / 2
2295
+ fits = "yes" if mem_bf16 <= BUDGET_GB else f"no (needs {mem_bf16:.1f} GB)"
2296
+ print(f"{model:50s} bf16={mem_bf16:6.1f} GB int8={mem_int8:6.1f} GB fits={fits}")
2297
+ ```
2298
+
2299
+ #### Workflow 7: "I hit an error and want to file a useful bug report"
2300
+
2301
+ ```bash
2302
+ # Capture the environment for the bug template
2303
+ ssmforge doctor --format json > doctor.json
2304
+
2305
+ # Capture the failing model
2306
+ ssmforge arch Qwen/Qwen2-X --dry-run --quiet --format json > profile.json
2307
+
2308
+ # Send both to the issue tracker
2309
+ cat > bug-report.md <<EOF
2310
+ **Environment:**
2311
+ \`\`\`
2312
+ $(cat doctor.json)
2313
+ \`\`\`
2314
+
2315
+ **Model profile (dry-run):**
2316
+ \`\`\`
2317
+ $(cat profile.json)
2318
+ \`\`\`
2319
+
2320
+ **Failing command:**
2321
+ \`\`\`
2322
+ $(cat failing-cmd.sh)
2323
+ \`\`\`
2324
+ EOF
2325
+ ```
2326
+
2327
+ ### 17.6 Web interfaces — what users see
2328
+
2329
+ ssmforge has two web surfaces that users encounter: the **PyPI page**
2330
+ and the **GitHub repository**. Both are part of the product — a
2331
+ polished README makes them useful, a confusing one means users give up.
2332
+
2333
+ #### PyPI page (https://pypi.org/project/ssmforge/)
2334
+
2335
+ When a user runs `pip install ssmforge`, they land here. What they see:
2336
+
2337
+ **Left sidebar** — package metadata:
2338
+
2339
+ ```
2340
+ ssmforge 0.2.3
2341
+ pip install ssmforge
2342
+ ```
2343
+
2344
+ Below that, the **classifiers** (configured in `pyproject.toml`):
2345
+ - `Development Status :: 4 - Beta` — honest staging
2346
+ - `Environment :: Console`
2347
+ - `Intended Audience :: Developers`
2348
+ - `License :: OSI Approved :: Apache Software License`
2349
+ - `Operating System :: OS Independent`
2350
+ - `Programming Language :: Python :: 3`
2351
+ - `Programming Language :: Python :: 3 :: Only`
2352
+ - `Programming Language :: Python :: 3.10` through `3.13`
2353
+
2354
+ These are searchable on PyPI — users find ssmforge by filtering
2355
+ "License :: Apache" or "Python :: 3.12".
2356
+
2357
+ **Center top** — package description. This comes from the `description`
2358
+ field in `pyproject.toml`, which defers to the README's first few
2359
+ paragraphs. PyPI also auto-renders badges below it:
2360
+
2361
+ ```
2362
+ Version: 0.2.3 License: Apache-2.0
2363
+ Status: Production/Stable Released: 23 hours ago
2364
+ ```
2365
+
2366
+ **Center middle** — **Project description**. This is the **rendered
2367
+ README**, which is why investing 1800 lines pays off:
2368
+
2369
+ - The TOC at the top becomes a contents sidebar
2370
+ - Code blocks show syntax-highlighted bash/python
2371
+ - Tables render with proper grid alignment
2372
+ - Internal anchor links work (the user's table of contents)
2373
+
2374
+ **Files tab** — lists all wheels and sdists for each version. For ssmforge:
2375
+
2376
+ ```
2377
+ ssmforge-0.2.3-py3-none-any.whl 68 KB Aug 23 19:27
2378
+ ssmforge-0.2.3.tar.gz 113 KB Aug 23 19:27
2379
+ ssmforge-0.2.2-... ... ...
2380
+ ... (8 versions total)
2381
+ ```
2382
+
2383
+ **Release history** — every uploaded version, clickable. Users can see
2384
+ "this project has been actively maintained" by viewing release dates.
2385
+
2386
+ #### Best practices for users browsing PyPI
2387
+
2388
+ - The README's TOC (`## Contents`) becomes a clickable sidebar.
2389
+ - Code blocks have proper language hints (`\`\`\`bash`) for highlighting.
2390
+ - Internal links (`[text](#anchor)`) work — the README is the canonical
2391
+ doc, not just a marketing page.
2392
+
2393
+ #### GitHub repository (https://github.com/lordxmen2k/SSMForge)
2394
+
2395
+ The other user-facing surface. What users encounter:
2396
+
2397
+ **Top of the repo** — the **README badge** at the top (looks the same
2398
+ as PyPI). Below that:
2399
+
2400
+ ```
2401
+ ssmforge 0.2.3 • Updated 23 hours ago
2402
+ A clean architecture analyzer for HuggingFace models — inspect quirks
2403
+ before committing to a 30-minute conversion.
2404
+
2405
+ [Code] [Issues] [Pull requests] [Discussions] (depends on repo settings)
2406
+ ```
2407
+
2408
+ **Right sidebar:**
2409
+
2410
+ - **About** section: short description, topics, website
2411
+ - **Releases** section: every tagged version with notes
2412
+ - **Packages** — if the repo publishes to PyPI, PyPI links here
2413
+ - **Contributors** — auto-tracked
2414
+
2415
+ **Code browser** — clicks on any file, full history visible, blame
2416
+ annotations on every line.
2417
+
2418
+ **Issues tab** — users post bug reports here. Make sure this is enabled
2419
+ in repo Settings → Features. Required for the bug-recipe above.
2420
+
2421
+ **Discussions tab** — opt-in feature (Settings → Features → Discussions).
2422
+ Best for Q&A, "how do I", share-what-you-built. Optional but nice for
2423
+ community projects.
2424
+
2425
+ **Wiki tab** — GitHub-hosted wiki. Optional. We use the GitHub README
2426
+ instead.
2427
+
2428
+ **Insights → Pulse** — git activity graphs over time. Users can see commit
2429
+ frequency trends here.
2430
+
2431
+ #### How to set up the GitHub web interface
2432
+
2433
+ For a project like ssmforge, the minimum GitHub setup is:
2434
+
2435
+ 1. **Repo Settings → Features → Issues: ON** (so users can file bugs)
2436
+ 2. **Repo Settings → Options → Discussions: ON** (optional, for Q&A)
2437
+ 3. **Repo Insights → Community Standards** — add a short CODE_OF_CONDUCT.md and CONTRIBUTING.md
2438
+ 4. **Tags/releases** — every version bump makes a release with notes (this README already has full release notes)
2439
+
2440
+ The README is the landing page for both PyPI and GitHub. Invest in it.
2441
+
2442
+ ### 17.7 Batch processing — file-by-file loops
2443
+
2444
+ For power users processing many models. Two patterns:
2445
+
2446
+ **Shell loop:**
2447
+
2448
+ ```bash
2449
+ #!/bin/bash
2450
+ # inspect_all.sh — generate one .json per model in models.txt
2451
+ mkdir -p outputs/
2452
+ while read -r model; do
2453
+ safe_name=$(echo "$model" | tr '/' '_' | tr -d ' ')
2454
+ ssmforge arch "$model" --dry-run --quiet --format json --output "outputs/${safe_name}.json"
2455
+ printf " %s\n" "$model"
2456
+ done < models.txt
2457
+ ```
2458
+
2459
+ **Python loop:**
2460
+
2461
+ ```python
2462
+ # inspect_all.py
2463
+ import subprocess, json
2464
+ from pathlib import Path
2465
+
2466
+ MODELS = open("models.txt").read().splitlines()
2467
+ OUT = Path("outputs"); OUT.mkdir(exist_ok=True)
2468
+
2469
+ results = {}
2470
+ for model in MODELS:
2471
+ r = subprocess.run(
2472
+ ["ssmforge", "arch", model, "--dry-run", "--quiet", "--format", "json"],
2473
+ capture_output=True, text=True,
2474
+ )
2475
+ if r.returncode != 0:
2476
+ results[model] = {"error": r.stderr.strip()}
2477
+ continue
2478
+ profile = json.loads(r.stdout)
2479
+ results[model] = profile
2480
+
2481
+ # Cross-reference: which models have which quirks
2482
+ from collections import defaultdict
2483
+ quirk_to_models = defaultdict(list)
2484
+ for model, profile in results.items():
2485
+ if "error" in profile:
2486
+ continue
2487
+ for quirk, value in profile.get("quirks", {}).items():
2488
+ if value is True:
2489
+ quirk_to_models[quirk].append(model)
2490
+
2491
+ print("Quirk summary across all models:")
2492
+ for quirk, models in sorted(quirk_to_models.items()):
2493
+ print(f" {quirk:25s} {len(models):>3} models: {', '.join(models[:3])}{'...' if len(models) > 3 else ''}")
2494
+ ```
2495
+
2496
+ ### 17.8 Troubleshooting cookbook
2497
+
2498
+ Common issues → one-line fixes:
2499
+
2500
+ | Symptom | Cause | Fix |
2501
+ |---------|-------|-----|
2502
+ | `ssmforge: command not found` | Not on PATH | `pip install -e ".[dev]"` in a venv, or use `python -m ssmforge.cli` |
2503
+ | `bash: q.md: Permission denied` | `>` redirect to unwritable dir | Use `--output PATH` with quoted relative path |
2504
+ | Output looks mangled (`C:Users...`) | Git Bash stripped backslashes | Wrap `--output` value in quotes, or use forward slashes |
2505
+ | `ModuleNotFoundError: No module named 'ssmforge'` | Wrong Python / wrong venv | Activate your project venv first |
2506
+ | `Error analyzing X: OSError: X is not a local folder` | Bad model id | Use full HF id like `org/repo` or a real local path |
2507
+ | Empty output | `--quiet` and pipe quirk | Try without `--quiet` and look at stderr |
2508
+ | Tests skipping on Windows | Permission differences | Tests use `monkeypatch.chmod` which Windows ignores; some are skipped explicitly |
2509
+ | `Killed` (exit 137) | OOM during weight load | Use `--dry-run` to preview without loading weights |
2510
+
2511
+ ### 17.9 Recipe index — quick lookup
2512
+
2513
+ Copy-paste recipes for the most common queries.
2514
+
2515
+ **Inspect the smallest possible model:**
2516
+
2517
+ ```bash
2518
+ ssmforge arch hf-internal-testing/tiny-random-LlamaForCausalLM --dry-run
2519
+ ```
2520
+
2521
+ **Compare 2 production models:**
2522
+
2523
+ ```bash
2524
+ ssmforge arch --compare TinyLlama/TinyLlama-1.1B-Chat-v1.0 \
2525
+ Qwen/Qwen2-1.5B-Instruct \
2526
+ --dry-run --format markdown
2527
+ ```
2528
+
2529
+ **Generate a graph for GitHub:**
2530
+
2531
+ ```bash
2532
+ ssmforge arch Qwen/Qwen2-0.5B-Instruct --dry-run --graph --format markdown \
2533
+ --output ~/Desktop/qwen2-graph.md
2534
+ ```
2535
+
2536
+ **Save a report and pipe to jq:**
2537
+
2538
+ ```bash
2539
+ ssmforge arch Qwen/Qwen2-7B-Instruct --dry-run --quiet --format json \
2540
+ --output /tmp/qwen2.json
2541
+ jq '.quirks | to_entries | map(select(.value == true))' /tmp/qwen2.json
2542
+ ```
2543
+
2544
+ **Run from a script (CI/CD):**
2545
+
2546
+ ```bash
2547
+ ssmforge arch $MODEL --dry-run --quiet --format json | python -c "
2548
+ import json, sys
2549
+ data = json.load(sys.stdin)
2550
+ sys.exit(0 if data['compatibility']['is_compatible'] else 1)
2551
+ "
2552
+ ```
2553
+
2554
+ **Test on a local model:**
2555
+
2556
+ ```bash
2557
+ ssmforge arch /path/to/local/model --dry-run
2558
+ # or for the full load:
2559
+ ssmforge arch /path/to/local/model
2560
+ ```
2561
+
2562
+ **Generate a comparison table for a doc:**
2563
+
2564
+ ```bash
2565
+ ssmforge arch --compare Qwen2-0.5B Qwen2-1.5B Qwen2-7B Qwen2-72B \
2566
+ --dry-run --only-different --format markdown \
2567
+ --output qwen2-family.md
2568
+ ```
2569
+
2570
+
1760
2571
 
1761
2572
  Bug reports and feature requests welcome:
1762
2573
  https://github.com/lordxmen2k/SSMForge/issues