hugpy-discovery 0.1.1__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 (92) hide show
  1. hugpy_discovery-0.1.1/PKG-INFO +16 -0
  2. hugpy_discovery-0.1.1/README.md +275 -0
  3. hugpy_discovery-0.1.1/pyproject.toml +32 -0
  4. hugpy_discovery-0.1.1/setup.cfg +4 -0
  5. hugpy_discovery-0.1.1/src/hugpy_discovery/__init__.py +2 -0
  6. hugpy_discovery-0.1.1/src/hugpy_discovery/__main__.py +187 -0
  7. hugpy_discovery-0.1.1/src/hugpy_discovery/analysis.py +531 -0
  8. hugpy_discovery-0.1.1/src/hugpy_discovery/catalog.py +72 -0
  9. hugpy_discovery-0.1.1/src/hugpy_discovery/dependencies.py +167 -0
  10. hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/__init__.py +6 -0
  11. hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/documentation.py +64 -0
  12. hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/documentation.sql +28 -0
  13. hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/__init__.py +2 -0
  14. hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/engine_probes.sql +18 -0
  15. hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/workflow.py +152 -0
  16. hugpy_discovery-0.1.1/src/hugpy_discovery/engines.py +271 -0
  17. hugpy_discovery-0.1.1/src/hugpy_discovery/environment/__init__.py +28 -0
  18. hugpy_discovery-0.1.1/src/hugpy_discovery/environment/environment.py +374 -0
  19. hugpy_discovery-0.1.1/src/hugpy_discovery/environment/environment.sql +33 -0
  20. hugpy_discovery-0.1.1/src/hugpy_discovery/filesystems.py +118 -0
  21. hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/__init__.py +15 -0
  22. hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/formula_catalog.py +118 -0
  23. hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/formula_catalog.sql +55 -0
  24. hugpy_discovery-0.1.1/src/hugpy_discovery/history/__init__.py +9 -0
  25. hugpy_discovery-0.1.1/src/hugpy_discovery/history/history.py +70 -0
  26. hugpy_discovery-0.1.1/src/hugpy_discovery/history/history.sql +11 -0
  27. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/__init__.py +46 -0
  28. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/api.py +61 -0
  29. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/audit.py +91 -0
  30. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/downloads.py +67 -0
  31. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/identity.py +127 -0
  32. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/__init__.py +16 -0
  33. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/metadata.py +350 -0
  34. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/metadata.sql +19 -0
  35. hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/token.py +54 -0
  36. hugpy_discovery-0.1.1/src/hugpy_discovery/identity.py +206 -0
  37. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/__init__.py +79 -0
  38. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/classes.py +19 -0
  39. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/constants.py +417 -0
  40. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/__init__.py +30 -0
  41. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/discovery_paths.py +8 -0
  42. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/environment.py +34 -0
  43. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/huggingface.py +115 -0
  44. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/repositories.py +18 -0
  45. hugpy_discovery-0.1.1/src/hugpy_discovery/imports/init_imports.py +157 -0
  46. hugpy_discovery-0.1.1/src/hugpy_discovery/inventory.py +484 -0
  47. hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/__init__.py +10 -0
  48. hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/memory_ticks.py +194 -0
  49. hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/memory_ticks.sql +30 -0
  50. hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/__init__.py +5 -0
  51. hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/operator_environment.py +19 -0
  52. hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/operator_environment.sql +17 -0
  53. hugpy_discovery-0.1.1/src/hugpy_discovery/persistence.py +26 -0
  54. hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/__init__.py +29 -0
  55. hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/preparation.py +593 -0
  56. hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/preparation.sql +156 -0
  57. hugpy_discovery-0.1.1/src/hugpy_discovery/quantification.py +26 -0
  58. hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/__init__.py +5 -0
  59. hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/runtime_evidence.py +8 -0
  60. hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/runtime_evidence.sql +39 -0
  61. hugpy_discovery-0.1.1/src/hugpy_discovery/store/__init__.py +6 -0
  62. hugpy_discovery-0.1.1/src/hugpy_discovery/store/schema.py +196 -0
  63. hugpy_discovery-0.1.1/src/hugpy_discovery/store/schema.sql +159 -0
  64. hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/__init__.py +8 -0
  65. hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/timing_scales.py +303 -0
  66. hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/timing_scales.sql +60 -0
  67. hugpy_discovery-0.1.1/src/hugpy_discovery/verification.py +184 -0
  68. hugpy_discovery-0.1.1/src/hugpy_discovery/viewer.html +123 -0
  69. hugpy_discovery-0.1.1/src/hugpy_discovery/viewer.py +312 -0
  70. hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/__init__.py +10 -0
  71. hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/weight_components.py +97 -0
  72. hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/weight_components.sql +51 -0
  73. hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/__init__.py +6 -0
  74. hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/worker_engines.py +104 -0
  75. hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/worker_engines.sql +30 -0
  76. hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/__init__.py +5 -0
  77. hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/workflow.py +57 -0
  78. hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/workflow.sql +46 -0
  79. hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/__init__.py +5 -0
  80. hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/wrapper_loads.py +96 -0
  81. hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/wrapper_loads.sql +20 -0
  82. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/PKG-INFO +16 -0
  83. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/SOURCES.txt +90 -0
  84. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/dependency_links.txt +1 -0
  85. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/entry_points.txt +2 -0
  86. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/requires.txt +14 -0
  87. hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/top_level.txt +1 -0
  88. hugpy_discovery-0.1.1/tests/test_formula_persistence.py +89 -0
  89. hugpy_discovery-0.1.1/tests/test_formulas.py +69 -0
  90. hugpy_discovery-0.1.1/tests/test_geometry.py +49 -0
  91. hugpy_discovery-0.1.1/tests/test_pipeline.py +174 -0
  92. hugpy_discovery-0.1.1/tests/test_precalculated_tiers.py +86 -0
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.4
2
+ Name: hugpy-discovery
3
+ Version: 0.1.1
4
+ Summary: Independent model inventory and host-scoped engine route evidence
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: hugpy-resources<0.2,>=0.1.2.8
7
+ Requires-Dist: sentencepiece>=0.2
8
+ Requires-Dist: protobuf>=4
9
+ Requires-Dist: hugpy-settings>=0.1.7
10
+ Provides-Extra: test
11
+ Requires-Dist: pytest<10,>=8; extra == "test"
12
+ Provides-Extra: identity
13
+ Requires-Dist: huggingface_hub>=0.20; extra == "identity"
14
+ Provides-Extra: huggingface
15
+ Requires-Dist: huggingface_hub>=0.20; extra == "huggingface"
16
+ Requires-Dist: requests>=2; extra == "huggingface"
@@ -0,0 +1,275 @@
1
+ # Hugpy Discovery
2
+
3
+ Worker engine wiring and the schema-10 history import are documented in
4
+ [Wrapper engine observations](docs/worker-engine-observations.md). The populated
5
+ older snapshots remain historical; imports never promote their readiness gates.
6
+
7
+ Standalone inventory, verification and pre-engine evidence for a local model tree. Source model files are read without modification; observations and proofs are written to a separate SQLite database. This package has its own scanner, format readers, engine survey, and browser inspector. It does not import the wrapper application or use its model-record writer.
8
+
9
+ ## Source layout
10
+
11
+ `hugpy-resources` is the canonical reference for generic functions, format
12
+ constants and MIME data. Discovery imports those implementations through its
13
+ `imports/init_imports.py` boundary. Its `imports/__init__.py` and
14
+ `imports/functions/__init__.py` retain the existing shared symbol exports.
15
+
16
+ | Owner | Responsibility |
17
+ | --- | --- |
18
+ | Resources `imports/functions/json_utils.py`, `formatting.py`, `ast_utils.py` | Serialization, digests, byte formatting and AST helpers |
19
+ | Resources `imports/functions/paths.py`, `locking.py`, `sqlite.py`, `sqlite_connections.py` | Generic filesystem, locking and SQLite utilities |
20
+ | Resources `imports/functions/file_types.py`, `tensor_files.py`, `gguf_*.py` | MIME hints, bounded file identification, tensor headers and GGUF readers |
21
+ | Resources `imports/functions/content_proofs.py` | Stable whole-file SHA256 and Git-blob SHA1 proofs |
22
+ | Resources `imports/constants.py`, `imports/mime_types.json`, `imports/classes.py` | Shared format metadata, MIME definitions, sentinels and parsing errors |
23
+ | Discovery `imports/functions/environment.py`, `repositories.py`, `huggingface.py` | Hugpy environment attribution and provider-specific validation/serialization |
24
+ | Discovery `imports/functions/discovery_paths.py` | Apply Discovery's directory exclusion policy to the generic snapshot helper |
25
+ | Discovery `huggingface/` | HF identity, provider metadata cache, search and explicit snapshot tools |
26
+
27
+ Moved generic helper scripts are removed from Discovery; Resources owns their
28
+ implementations and data. Source fingerprints include the shared package's
29
+ Python and data files. Optional tokenizer and provider SDKs resolve only when
30
+ the corresponding feature requests them. Resources' base install remains
31
+ standard-library-only; `hugpy-resources[inspection]` supplies optional tokenizer
32
+ inspection dependencies.
33
+
34
+ Discovery ledger writes, preparation/readiness decisions, engine surveys and
35
+ Hugpy-specific source pointers remain in their domain modules. The standalone
36
+ engine probe lives in `imports.constants.PROBE` and runs in the surveyed
37
+ environment.
38
+
39
+ Each SQL schema lives with its companion Python code in a package beneath
40
+ `src/hugpy_discovery/`. Each SQL file has a matching Python implementation beside
41
+ it: for example, `preparation/preparation.sql` and `preparation/preparation.py`,
42
+ or `store/schema.sql` and `store/schema.py`. Package `__init__.py` files only
43
+ export the public functions and constants, preserving imports such as
44
+ `hugpy_discovery.preparation`.
45
+
46
+ | Directory | SQL file | Companion Python responsibility |
47
+ | --- | --- | --- |
48
+ | `store/` | `schema.sql` | SQLite store and migration ordering |
49
+ | `preparation/` | `preparation.sql` | Intake and preparation ledger |
50
+ | `environment/` | `environment.sql` | Environment source registry |
51
+ | `operator_environment/` | `operator_environment.sql` | Shared operator contract projection |
52
+ | `documentation/` | `documentation.sql` | Document imports and revisions |
53
+ | `workflow/` | `workflow.sql` | Connected evidence overview |
54
+ | `formula_catalog/` | `formula_catalog.sql` | Formula contracts, sources and validation |
55
+ | `worker_engines/` | `worker_engines.sql` | Historical engine observation imports |
56
+ | `memory_ticks/` | `memory_ticks.sql` | Capacity, memory scenarios and tick ladders |
57
+ | `wrapper_loads/` | `wrapper_loads.sql` | Historical load measurement imports |
58
+ | `runtime_evidence/` | `runtime_evidence.sql` | Runtime provenance schema migration |
59
+ | `weight_components/` | `weight_components.sql` | Disjoint weight accounting |
60
+
61
+ `preparation` continues to export its memory scenario helpers, `environment`
62
+ exports `persist_contract`, and `worker_engines` exports `import_loads` for
63
+ existing callers. SQL files are included as subpackage resources in the wheel.
64
+
65
+ ## Preparation and evidence
66
+
67
+ The [formula and validation reference](docs/formulas-and-validation.md) records
68
+ the offline test suite, ten formula contracts, pinned upstream sources and
69
+ existing geometry pointers. Schema v9 stores validation reports and a separate
70
+ static geometry review; incomplete memory totals remain NULL.
71
+
72
+ The [initial operator environment contract](docs/operator-environment-contract.md)
73
+ defines the eleven retained keys, their default pointers and migration aliases.
74
+ Schema v6 exposes this contract alongside the broader source audit; third-party
75
+ additions are deferred. Live service configuration has not yet been migrated.
76
+
77
+ ## Assembly before derivation
78
+
79
+ The current review flow is:
80
+
81
+ ```text
82
+ Saved documentation + eleven-key contract + environment source audit
83
+ ↓
84
+ Literal intake → declared stores/owners → filesystem and file locations
85
+ ↓
86
+ Provider identity → selected units and dependencies → current file proofs
87
+ ↓
88
+ pre_derivation_review: requirements passed or explicit blockers
89
+ ↓
90
+ Static geometry / memory evidence review → controlled engine checks (not attempted)
91
+ ```
92
+
93
+ Use `prepare --stop-before-derivation` to refresh and connect the existing
94
+ evidence without computing geometry or memory scenarios. Repeat `--document`
95
+ to capture the associated Markdown in the same workflow:
96
+
97
+ ```sh
98
+ .venv/bin/python -m hugpy_discovery prepare \
99
+ --database artifacts/pre-engine-v9.sqlite3 \
100
+ --env-file /etc/hugpy/wrapper.env --stop-before-derivation \
101
+ --document README.md --document docs/operator-environment-contract.md
102
+ ```
103
+
104
+ For a full documentation snapshot, pass all session documents, as in `save-docs`
105
+ below. With no `--document`, preparation binds the most recent saved import.
106
+ `preparation_context` pins the documentation import, source-registry run and
107
+ exact shared contract JSON/hash. `pre_derivation_review` joins current engine
108
+ candidates to units, ownership, filesystem identity, allowance, selected-file
109
+ verification and eight prerequisite gates. Context blockers remain explicit.
110
+ Preparation rechecks file stat identities and reuses completed proofs; it does
111
+ not read full weight payloads, fetch provider metadata or run benchmarks.
112
+
113
+ `current_execution_readiness` selects the latest completed preparation run;
114
+ historical candidates remain in `execution_plans`. Earlier geometry and memory
115
+ rows remain available, but deferred stages do not recompute or validate them.
116
+ The separate `formula-catalog --derive-static` command refreshes static evidence
117
+ after a passing offline suite, preserving that preparation history.
118
+ This joins the staging evidence flow; live Wrapper/Core configuration migration
119
+ and undeclared ownership remain separate outstanding work.
120
+
121
+ ## Documentation snapshots
122
+
123
+ Schema v7 stores full Markdown content with source paths, SHA256 digests,
124
+ capture times and source stat identities. `documentation_current` exposes the
125
+ latest saved text for each document; `documentation_revisions` preserves older
126
+ content. Unchanged imports reuse a revision and record a new observation.
127
+ Source files remain in place. Capturing a document does not turn its historical
128
+ claims into current runtime evidence. Imports are explicit snapshots, not an
129
+ automatic filesystem watcher.
130
+
131
+ ```sh
132
+ .venv/bin/python -m hugpy_discovery save-docs \
133
+ --database artifacts/pre-engine-v9.sqlite3 \
134
+ README.md docs/*.md \
135
+ ../hugpy-settings/package/README.md
136
+ ```
137
+
138
+ The inspector searches document text using its normal table search. Select a
139
+ row in `documentation_current` to read `content_markdown`. Markdown is displayed
140
+ as text, so embedded HTML and scripts are never executed.
141
+
142
+ ## Build and inspect
143
+
144
+ ```sh
145
+ .venv/bin/python -m hugpy_discovery build /path/to/models --database artifacts/discovery.sqlite3
146
+ .venv/bin/python -m hugpy_discovery serve /path/to/models --output artifacts --database artifacts/discovery.sqlite3
147
+ ```
148
+
149
+ `build` creates a **new** database outside the model tree. An existing database is never overwritten. `--engine-python /path/to/python` may be repeated to include specific engine environments. The built-in survey checks a bounded set of local interpreters and native binaries before scanning models. Its results are scoped to this host and the surveyed executables; they do not describe remote fleet capacity.
150
+
151
+ The static `build` evidence path is:
152
+
153
+ 1. Record engine package presence, Transformers loader registration, and host hardware.
154
+ 2. Inventory the model tree, attribute directories/files to shared filesystem records, and inspect bounded file headers, manifests, and config documents.
155
+ 3. Form weight sets, shard groups, and component dependencies. Keep alternative weight variants separate.
156
+ 4. Derive per-bundle engine routes with explicit blockers or a `static-candidate` state.
157
+ 5. Validate database references, estimate coverage, and source metadata stability.
158
+
159
+ `static-candidate` requires complete dependency evidence and a known loader mapping. Other routes retain `dependency-unresolved` or `loader-unresolved`. Even a `static-candidate` does **not** mean a model will load, fit memory, or run correctly. Static source stability is based on directory metadata plus hashes of inspected evidence bytes; `build` does not content-hash tensor payloads. The separate `prepare` and `verify` stages record readiness requirements and full-file proofs before a guarded engine check. Loader-specific files, custom code, version support, memory allocation, and runtime behavior remain to be checked by engine-specific execution in a later stage.
160
+
161
+ The original discovery prototype and its SQLite database remain in the wrapper staging tree as historical evidence. New discovery passes and the inspector should use this package and its own database.
162
+
163
+ ## Filesystem attribution
164
+
165
+ Schema v2 adds `filesystem_info`; `model_records.filesystem_id` and
166
+ `model_record_files.filesystem_id` reference it. Many models share one filesystem
167
+ row. File references describe the resolved file location, including a file on a
168
+ different filesystem from its model directory. The filesystem row records UUID
169
+ and PARTUUID when visible through `/dev/disk`, observed device major/minor and
170
+ path, filesystem type, mount entries/options, capacity and observation time.
171
+ Mount entries are plural because bind mounts can expose the same filesystem at
172
+ several paths with different options.
173
+
174
+ The primary key uses the host and observed filesystem UUID when available;
175
+ otherwise it uses the host, boot and observed filesystem device. UUID is not
176
+ assumed globally unique across hosts. Unknown identifiers remain NULL.
177
+ This is local observation, not fleet store identity or
178
+ a physical-disk topology inventory. Ownership, model allowance and write/delete
179
+ authority belong to declared stores/access policy; mount `rw` grants none of
180
+ those permissions. No write probe or throughput benchmark runs here.
181
+
182
+ Opening a v1 database through the writable Store adds the references, leaving
183
+ historical rows unattributed. The read-only inspector does not migrate a database.
184
+ A fresh build populates current filesystem observations. Legacy `drive_*` columns
185
+ remain for compatibility; new consumers should join `filesystem_info`.
186
+
187
+ ## Intake and ownership target
188
+
189
+ The next rung follows the [D1–D6 storage ownership contract](../hugpy-resources/docs/nomenclature.md): local declarations establish authority; Wrappers host and serve worker and central stores with separate budgets; Core consolidates their evidence and coordinates sharing. Undeclared drives are immutable. Configuration cleanup and host/drive intake must precede engine probes in that target flow.
190
+
191
+ ## Model identity resolver
192
+
193
+ The HF resolver uses Discovery's own `huggingface.identity` adapter,
194
+ `ModelMetadataStore` and shared `serialize_model_info` helper, extracted from
195
+ Storage. Install the `identity` extra; no Storage package is needed for these
196
+ lookups. For this staging checkout:
197
+
198
+ ```sh
199
+ .venv/bin/python -m pip install -e '.[identity]'
200
+ .venv/bin/python -m hugpy_discovery resolve --database artifacts/discovery.sqlite3 --all
201
+ .venv/bin/python -m hugpy_discovery resolve --database artifacts/discovery.sqlite3 --model-dir /absolute/model/directory --offline
202
+ ```
203
+
204
+ `--all` processes model directories with artifacts or configuration, skipping
205
+ empty inventory-only directories. `--worker` scopes a worker and `--limit` bounds
206
+ a batch. `build --resolve-identities` enriches a fresh inventory after its static
207
+ pass. Ordinary builds remain offline with respect to model providers.
208
+
209
+ The default cache is `provider-metadata.sqlite3` beside the discovery database
210
+ (or in the inspector's output directory). `--provider-cache` selects another
211
+ cache outside model trees. Successful responses persist without expiry;
212
+ `--refresh` explicitly replaces them, and `--offline` uses only cached results.
213
+ Errors remain distinct from empty search results and receive a ten-minute
214
+ retry delay. Credentials use Hugging Face's environment/saved token resolution;
215
+ requests are restricted to `https://huggingface.co`. Cache keys separate credential
216
+ scopes without storing tokens. No root provisioning helpers are imported.
217
+
218
+ The inspector serves these operations:
219
+
220
+ | Method and route | JSON body / query |
221
+ | --- | --- |
222
+ | `POST /api/identity/search` | `{"query":"model name","limit":5}` |
223
+ | `POST /api/identity/describe` | `{"model_id":"owner/repository","revision":"optional revision"}` |
224
+ | `POST /api/identity/resolve` | `{"model_dir":"/absolute/model/directory"}`; optional `worker` |
225
+ | `GET /api/identity/resolution` | `model_dir` and optional `worker`; reads the latest persisted result |
226
+
227
+ POST bodies must use `Content-Type: application/json`. Optional `offline` and
228
+ `refresh` booleans apply to the three POST operations. The initial provider is
229
+ `hf`; other provider names are rejected explicitly. The inspector's model-record
230
+ details also offer **Resolve identity**.
231
+
232
+ Schema v3 retains resolution history and candidate/provider evidence. Exact
233
+ repository hints plus matching local-inventory filenames and sizes can produce
234
+ `metadata-supported`; that status populates `hub_id` with an explicit
235
+ `hub_id_source`. Name-search matches stay candidates. Disagreement, ambiguity,
236
+ provider failures and offline cache misses remain visible. Comparisons use the
237
+ recorded scan and retain its input signature; this does not revalidate disk
238
+ contents. A provider's current commit is stored as `provider_revision`, never
239
+ silently assigned to the local `revision`. No weight hashing, downloading,
240
+ loading or geometry derivation is performed by identity resolution.
241
+
242
+
243
+ ## Hugging Face tools
244
+
245
+ Discovery owns Hugging Face identity, metadata caching, search, repository size
246
+ lookups, snapshot audit and explicit repair/download helpers under
247
+ `src/hugpy_discovery/huggingface/`. Install `.[huggingface]` for the full tool
248
+ set, including token validation. See [Hugging Face extraction](docs/huggingface-tools.md)
249
+ for source ownership, cache paths and examples. Storage's implementation remains
250
+ intact. File verification now uses the identical content-hashing implementation
251
+ from Resources, so Discovery no longer imports Storage.
252
+
253
+
254
+ Internal imports use relative paths. Shared schemas, catalog metadata, status
255
+ sets, and option lists live in `imports/constants.py`; workflow modules import
256
+ them at module scope. Optional provider SDKs, parser backends, and hardware
257
+ libraries remain deferred, as do documented imports that break workflow cycles.
258
+ Resource helpers resolve directly to their definitions in
259
+ `hugpy_resources.imports.functions` and `hugpy_resources.imports.constants`.
260
+
261
+ Shared metadata and exact NVML observations resolve through the Resources import
262
+ boundary. Discovery no longer imports Wrapper's NVML module. Discovery retains
263
+ provider/repository workflows and persistence; generic parsing stays in Resources
264
+ so lower-level consumers do not acquire a dependency on this application.
265
+
266
+ ## Embedding in Wrapper
267
+
268
+ `inventory.build_database(..., store=host_store)` and
269
+ `inventory.create_database(..., store=host_store)` accept a host-owned Store.
270
+ Wrapper supplies its own Store and applies its own migrations before Discovery
271
+ writes inventory, filesystem, tensor and route evidence. Discovery neither
272
+ opens its standalone Store nor closes the supplied Store. The existing
273
+ standalone commands retain their own separate schema for standalone use.
274
+ `catalog.discover` supplies bounded traversal with host callbacks for configured
275
+ roots/exclusions, quant election and runtime eligibility.
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "hugpy-discovery"
7
+ version = "0.1.1"
8
+ description = "Independent model inventory and host-scoped engine route evidence"
9
+ requires-python = ">=3.11"
10
+ dependencies = ["hugpy-resources>=0.1.2.8,<0.2", "sentencepiece>=0.2", "protobuf>=4", "hugpy-settings>=0.1.7"]
11
+
12
+ [project.optional-dependencies]
13
+ test = ["pytest>=8,<10"]
14
+ identity = ["huggingface_hub>=0.20"]
15
+ huggingface = ["huggingface_hub>=0.20", "requests>=2"]
16
+
17
+ [project.scripts]
18
+ hugpy-discovery = "hugpy_discovery.__main__:main"
19
+
20
+ [tool.setuptools]
21
+ package-dir = {"" = "src"}
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["src"]
25
+
26
+ [tool.setuptools.package-data]
27
+ hugpy_discovery = ["viewer.html"]
28
+ "*" = ["*.sql"]
29
+
30
+ [tool.pytest.ini_options]
31
+ testpaths = ["tests"]
32
+ addopts = "-ra"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ """Independent, read-only model discovery and engine route assessment."""
2
+
@@ -0,0 +1,187 @@
1
+ """CLI for the independent discovery package."""
2
+
3
+ from .inventory import build_database
4
+ from .worker_engines import (
5
+ import_loads,
6
+ import_observations,
7
+ )
8
+ from .store import Store
9
+ from .identity import (
10
+ resolve_database,
11
+ validate_output,
12
+ )
13
+ from .weight_components import derive
14
+ from .timing_scales import derive as derive_timing
15
+ from .formula_catalog import establish
16
+ from .documentation import import_documents
17
+ from .environment import build_registry
18
+ from .preparation import prepare
19
+ from .verification import verify
20
+ from .viewer import main as viewer_main
21
+ from .imports.init_imports import (
22
+ Path,
23
+ argparse,
24
+ json,
25
+ sys,
26
+ )
27
+
28
+
29
+ def main():
30
+ parser = argparse.ArgumentParser(description='Local model and engine evidence survey')
31
+ sub = parser.add_subparsers(dest='command',required=True)
32
+ build = sub.add_parser('build',help='create a fresh SQLite evidence database')
33
+ build.add_argument('root',type=Path)
34
+ build.add_argument('--database',required=True,type=Path)
35
+ build.add_argument('--engine-python',action='append',default=[])
36
+ build.add_argument('--resolve-identities', action='store_true', help='resolve observed models through the provider cache/API after inventory')
37
+ build.add_argument('--provider-cache', type=Path)
38
+ resolve = sub.add_parser('resolve', help='resolve observed model identities using existing provider metadata')
39
+ resolve.add_argument('--database', required=True, type=Path)
40
+ target = resolve.add_mutually_exclusive_group(required=True)
41
+ target.add_argument('--model-dir', type=Path)
42
+ target.add_argument('--all', action='store_true', help='resolve all nonempty model directories')
43
+ resolve.add_argument('--worker')
44
+ resolve.add_argument('--limit', type=int)
45
+ resolve.add_argument('--provider-cache', type=Path)
46
+ resolve.add_argument('--offline', action='store_true')
47
+ resolve.add_argument('--refresh', action='store_true')
48
+ prepare = sub.add_parser('prepare', help='build the complete pre-engine evidence/readiness database')
49
+ prepare.add_argument('--database', required=True, type=Path)
50
+ prepare.add_argument('--source-database', type=Path, help='copy an existing inventory to a new database first')
51
+ prepare.add_argument('--env-file', action='append', type=Path, default=[])
52
+ prepare.add_argument('--declarations', type=Path, help='explicit store ownership, execution paths, allowances and selections')
53
+ prepare.add_argument('--stop-before-derivation', action='store_true', help='connect existing evidence and record blockers without computing geometry or memory scenarios')
54
+ prepare.add_argument('--document', type=Path, action='append', default=[], help='Markdown to snapshot and bind to this run; repeatable')
55
+ verify = sub.add_parser('verify', help='process resumable full-file hash jobs; never loads engines')
56
+ verify.add_argument('--database', required=True, type=Path)
57
+ verify.add_argument('--byte-budget', type=int, default=64 * 1024**2)
58
+ verify.add_argument('--all-bytes', action='store_true', help='remove the per-invocation I/O byte budget')
59
+ verify.add_argument('--max-files', type=int)
60
+ verify.add_argument('--model-dir', type=Path)
61
+ verify.add_argument('--proofs-database', type=Path, help='reuse current Wrapper storage_content_hashes proofs read-only')
62
+ engines = sub.add_parser('import-wrapper-engines', help='import recorded worker engine readiness; source is read-only')
63
+ engines.add_argument('--database', required=True, type=Path)
64
+ engines.add_argument('--wrapper-database', required=True, type=Path)
65
+ engines.add_argument('--request-id')
66
+ engines.add_argument('--limit', type=int, default=1000, help='maximum recent calls to import')
67
+ components = sub.add_parser('derive-weight-components', help='derive expert/non-expert weight breakdown from recorded tensor facts')
68
+ components.add_argument('--database', required=True, type=Path)
69
+ timing = sub.add_parser('timing-scales', help='price every bundle, representation and placement per token from the box read rates')
70
+ timing.add_argument('--database', required=True, type=Path)
71
+ loads = sub.add_parser('import-wrapper-loads', help='import recorded transformers loads, measured decode and drive reads; source is read-only')
72
+ loads.add_argument('--database', required=True, type=Path)
73
+ loads.add_argument('--wrapper-database', required=True, type=Path, action='append')
74
+ registry = sub.add_parser('env-registry', help='record environment default/source pointers without applying configuration')
75
+ registry.add_argument('--database', required=True, type=Path)
76
+ registry.add_argument('--staging', required=True, type=Path)
77
+ registry.add_argument('--seed-report', required=True, type=Path)
78
+ registry.add_argument('--report', type=Path)
79
+ formulas = sub.add_parser('formula-catalog', help='record pinned formulas, implementation pointers and offline suite results')
80
+ formulas.add_argument('--database', required=True, type=Path)
81
+ formulas.add_argument('--manifest', required=True, type=Path)
82
+ formulas.add_argument('--staging', required=True, type=Path)
83
+ formulas.add_argument('--junit', type=Path)
84
+ formulas.add_argument('--derive-static', action='store_true')
85
+ documents = sub.add_parser('save-docs', help='save full Markdown documents and retain content revisions')
86
+ documents.add_argument('--database', required=True, type=Path)
87
+ documents.add_argument('paths', nargs='+', type=Path)
88
+ serve = sub.add_parser('serve',help='open the read-only inspector; build on demand')
89
+ serve.add_argument('root',type=Path)
90
+ serve.add_argument('--output',required=True,type=Path)
91
+ serve.add_argument('--database',type=Path)
92
+ serve.add_argument('--host',default='127.0.0.1')
93
+ serve.add_argument('--port',type=int,default=8766)
94
+ engine_probe = sub.add_parser('engine-discovery', help='collect runtime surveys and correlate probe evidence; never loads models')
95
+ engine_probe.add_argument('--database', required=True, type=Path)
96
+ engine_probe.add_argument('--wrapper-database', type=Path)
97
+ engine_probe.add_argument('--probe-results', action='append', type=Path, default=[])
98
+ engine_probe.add_argument('--survey', action='store_true')
99
+ engine_probe.add_argument('--engine-python', action='append', default=[])
100
+ engine_probe.add_argument('--limit', type=int, default=1000)
101
+ args = parser.parse_args()
102
+ if args.command == 'engine-discovery':
103
+ from .engine_probes import collect
104
+ print(json.dumps(collect(args.database, wrapper_database=args.wrapper_database,
105
+ result_paths=args.probe_results, survey=args.survey,
106
+ engine_paths=args.engine_python, limit=args.limit), indent=2))
107
+ return
108
+
109
+ if args.command == 'import-wrapper-engines':
110
+ print(json.dumps(import_observations(args.database, args.wrapper_database,
111
+ request_id=args.request_id, limit=args.limit), indent=2))
112
+ return
113
+ if args.command == 'derive-weight-components':
114
+ database = args.database.resolve(strict=True)
115
+ validate_output(database, database.parent / 'provider-metadata.sqlite3')
116
+ db = Store(database)
117
+ try:
118
+ with db.transaction() as conn:
119
+ report = derive(conn)
120
+ print(json.dumps(report, indent=2))
121
+ finally:
122
+ db.close()
123
+ return
124
+ if args.command == 'timing-scales':
125
+ database = args.database.resolve(strict=True)
126
+ validate_output(database, database.parent / 'provider-metadata.sqlite3')
127
+ db = Store(database)
128
+ try:
129
+ with db.transaction() as conn:
130
+ report = derive_timing(conn)
131
+ print(json.dumps(report, indent=2))
132
+ finally:
133
+ db.close()
134
+ return
135
+ if args.command == 'import-wrapper-loads':
136
+ print(json.dumps([import_loads(args.database, source) for source in args.wrapper_database], indent=2))
137
+ return
138
+ if args.command == 'formula-catalog':
139
+ print(json.dumps(establish(args.database,manifest=args.manifest,staging=args.staging,
140
+ junit=args.junit,derive_static=args.derive_static),indent=2))
141
+ return
142
+ if args.command == 'save-docs':
143
+ print(json.dumps(import_documents(args.database, args.paths), indent=2))
144
+ return
145
+ if args.command == 'env-registry':
146
+ print(json.dumps(build_registry(args.database, args.staging, args.seed_report, args.report), indent=2))
147
+ return
148
+ if args.command == 'prepare':
149
+ result = prepare(args.database, source_database=args.source_database, env_files=args.env_file,
150
+ declarations_path=args.declarations, stop_before_derivation=args.stop_before_derivation,
151
+ document_paths=args.document)
152
+ print(json.dumps(result, indent=2))
153
+ return
154
+ if args.command == 'verify':
155
+ result = verify(args.database, byte_budget=None if args.all_bytes else args.byte_budget,
156
+ max_files=args.max_files, model_dir=args.model_dir, proofs_database=args.proofs_database)
157
+ print(json.dumps(result, indent=2))
158
+ return
159
+ if args.command == 'resolve':
160
+ results = resolve_database(args.database, cache_path=args.provider_cache, model_dir=args.model_dir,
161
+ worker=args.worker, offline=args.offline, refresh=args.refresh, limit=args.limit)
162
+ print(json.dumps([dict(model_dir=r['model_dir'], status=r['status'], model_id=r['model_id'],
163
+ candidates=len(r['candidates'])) for r in results], indent=2))
164
+ return
165
+ if args.command=='serve':
166
+ sys.argv = [sys.argv[0],str(args.root),'--output',str(args.output),'--host',args.host,'--port',str(args.port)]
167
+ if args.database:
168
+ sys.argv.extend(['--database',str(args.database)])
169
+ viewer_main()
170
+ return
171
+ last_phase = None
172
+ def progress(**event):
173
+ nonlocal last_phase
174
+ phase = event.get('phase')
175
+ if phase != last_phase:
176
+ print(json.dumps({'phase': phase}), flush=True)
177
+ last_phase = phase
178
+ report=build_database(args.root,args.database,engine_paths=args.engine_python,progress=progress)
179
+ print(json.dumps(report['database'],indent=2,sort_keys=True))
180
+ if args.resolve_identities:
181
+ results = resolve_database(args.database, cache_path=args.provider_cache)
182
+ print(json.dumps({'identities': [dict(model_dir=r['model_dir'], status=r['status'],
183
+ model_id=r['model_id']) for r in results]}, indent=2))
184
+
185
+
186
+ if __name__=='__main__':
187
+ main()