Skip to content

Commit c9afed2

Browse files
authored
Merge pull request #160 from helpfulengineering/phase-2
Phase 2
2 parents 713c4fd + 11d1489 commit c9afed2

148 files changed

Lines changed: 124623 additions & 139 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.repo-map.md

Lines changed: 150 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ REPOSITORY MAP (Aider Style)
33
================================================================================
44
Repository: supply-graph-ai
55

6-
Total Python files: 280
6+
Total Python files: 287
77

88
├── demo/
99
│ ├── __init__.py
@@ -158,6 +158,22 @@ Total Python files: 280
158158
│ │ def save_okh_manifest()
159159
│ │ def save_okw_facility()
160160
│ │ def main()
161+
│ ├── okh_generation_baseline_report.py
162+
│ │ def main()
163+
│ ├── okh_generation_batch.py
164+
│ │ def _parse_args()
165+
│ │ def _select_repos()
166+
│ │ def main()
167+
│ ├── okh_generation_chunked_evaluation.py
168+
│ │ def _load_report()
169+
│ │ def _row_map()
170+
│ │ def _field_presence_score()
171+
│ │ def _summarize()
172+
│ │ def _paired_ids()
173+
│ │ def _compare_paired()
174+
│ │ def main()
175+
│ ├── okh_generation_layer_compare.py
176+
│ │ def main()
161177
│ ├── populate_ome_from_synthetic_data.py
162178
│ ├── setup_storage.py
163179
│ ├── validate_docs.py
@@ -619,9 +635,19 @@ Total Python files: 280
619635
│ │ │ class BOMBuilder (__init__, build_bom, _validate_components)
620636
│ │ ├── built_directory.py
621637
│ │ │ class BuiltDirectoryExporter (__init__, _bom_to_markdown, _bom_to_csv...)
638+
│ │ ├── dataset_generation.py
639+
│ │ │ def _default_log()
622640
│ │ ├── engine.py
623641
│ │ │ class EngineMetrics (__post_init__)
624642
│ │ │ class GenerationEngine (__init__, _validate_config, _initialize_matchers...)
643+
│ │ ├── gitlab_instance.py
644+
│ │ │ def normalize_http_url()
645+
│ │ │ def parse_self_hosted_gitlab_hosts()
646+
│ │ │ def gitlab_path_has_namespace_and_project()
647+
│ │ │ def is_allowlisted_self_hosted_gitlab_url()
648+
│ │ │ def is_gitlab_http_clone_url()
649+
│ │ │ def extract_gitlab_owner_repo_from_path()
650+
│ │ │ def gitlab_api_v4_base_url()
625651
│ │ ├── layers/
626652
│ │ │ ├── __init__.py
627653
│ │ │ ├── base.py
@@ -632,7 +658,9 @@ Total Python files: 280
632658
│ │ │ ├── heuristic.py
633659
│ │ │ │ class FilePattern
634660
│ │ │ │ class HeuristicMatcher (__init__, _initialize_file_patterns, _initialize_content_patterns...)
661+
│ │ │ │ def _is_license_like_file_path()
635662
│ │ │ ├── llm.py
663+
│ │ │ │ class ChunkedLLMReduceSchema
636664
│ │ │ │ class LLMGenerationLayer (__init__, _create_llm_service, _load_okh_schema_prompt...)
637665
│ │ │ └── nlp.py
638666
│ │ │ class EntityPattern
@@ -704,6 +732,18 @@ Total Python files: 280
704732
│ │ class TextProcessor (__init__, _initialize_license_patterns, _initialize_version_patterns...)
705733
│ ├── llm/
706734
│ │ ├── __init__.py
735+
│ │ ├── chunking.py
736+
│ │ │ class TokenEstimator (__call__)
737+
│ │ │ class TokenBudget
738+
│ │ │ class TokenBudgetPolicy
739+
│ │ │ class ChunkingConfig (__post_init__)
740+
│ │ │ class TextChunk
741+
│ │ │ def default_token_estimator()
742+
│ │ │ def build_token_budget()
743+
│ │ │ def split_text_into_chunks()
744+
│ │ │ def _max_end_for_budget()
745+
│ │ │ def _apply_boundary_preference()
746+
│ │ │ def _suffix_start_for_overlap()
707747
│ │ ├── models/
708748
│ │ │ ├── __init__.py
709749
│ │ │ ├── metrics.py
@@ -714,6 +754,9 @@ Total Python files: 280
714754
│ │ │ │ class LLMRequestType
715755
│ │ │ │ class LLMRequestConfig
716756
│ │ │ │ class LLMRequest (__post_init__)
757+
│ │ │ │ class LLMPayloadSection (__post_init__)
758+
│ │ │ │ class LLMTraceContext
759+
│ │ │ │ class LLMStructuredRequest (__post_init__)
717760
│ │ │ └── responses.py
718761
│ │ │ class LLMResponseStatus
719762
│ │ │ class LLMResponseMetadata
@@ -771,7 +814,7 @@ Total Python files: 280
771814
│ │ │ class ConnectionError
772815
│ │ └── service.py
773816
│ │ class LLMServiceConfig (__init__)
774-
│ │ class LLMService (__init__, _get_providers_to_try, _update_metrics...)
817+
│ │ class LLMService (__init__, _build_structured_prompt, _validate_response_schema...)
775818
│ ├── main.py
776819
│ ├── matching/
777820
│ │ ├── __init__.py
@@ -1181,7 +1224,7 @@ Total Python files: 280
11811224

11821225
## Overview
11831226

1184-
Total files analyzed: 280
1227+
Total files analyzed: 287
11851228

11861229
## Entry Points
11871230

@@ -2159,7 +2202,7 @@ This module provides data models for LLM metrics ...
21592202
21602203
This module provides data models for LLM requests...
21612204

2162-
**Exports:** LLMRequestType, LLMRequestConfig, LLMRequest
2205+
**Exports:** LLMRequestType, LLMRequestConfig, LLMRequest, LLMPayloadSection, LLMTraceContext
21632206

21642207
**Classes:**
21652208
- `LLMRequestType` (inherits: Enum)
@@ -2168,6 +2211,12 @@ This module provides data models for LLM requests...
21682211
- Configuration for LLM requests....
21692212
- `LLMRequest`
21702213
- Base LLM request model....
2214+
- `LLMPayloadSection`
2215+
- Named section of text for structured long-context workflows....
2216+
- `LLMTraceContext`
2217+
- Trace metadata for chunked or multi-step request execution....
2218+
- `LLMStructuredRequest`
2219+
- Structured request model for chunked map-reduce style workflows....
21712220

21722221
### `src/core/llm/models/responses.py`
21732222
> LLM Response Models for the Open Hardware Manager.
@@ -3403,6 +3452,48 @@ This script generates OKH and OKW files specifically designed ...
34033452
- `save_okh_manifest(manifest, output_path)`
34043453
- Save OKH manifest to JSON file....
34053454

3455+
### `scripts/okh_generation_baseline_report.py`
3456+
> Generate OKH generation baseline report (Issue 1.3.1 Phase B5).
3457+
3458+
Reads tests/data/okh_generation/rep...
3459+
3460+
**Exports:** main
3461+
3462+
**Functions:**
3463+
- `main()`
3464+
3465+
### `scripts/okh_generation_batch.py`
3466+
> Batch OKH generation for every supported entry in tests/data/okh_generation/repositories.json.
3467+
3468+
Writ...
3469+
3470+
**Exports:** main
3471+
3472+
**Functions:**
3473+
- `main()`
3474+
3475+
**Internal Dependencies:** 1 imports
3476+
3477+
### `scripts/okh_generation_chunked_evaluation.py`
3478+
> Evaluate chunked LLM canary quality gates against a baseline batch report.
3479+
3480+
This compares two batch ...
3481+
3482+
**Exports:** main
3483+
3484+
**Functions:**
3485+
- `main()`
3486+
3487+
### `scripts/okh_generation_layer_compare.py`
3488+
> Compare 3-layer vs 4-layer OKH manifests on disk (heuristic metrics).
3489+
3490+
For each supported repo in te...
3491+
3492+
**Exports:** main
3493+
3494+
**Functions:**
3495+
- `main()`
3496+
34063497
### `scripts/populate_ome_from_synthetic_data.py`
34073498
> Populate the Azure Blob Storage container "ome" with OKH and OKW files from synthetic_data/.
34083499
@@ -4256,6 +4347,11 @@ This module provides functionality...
42564347
- `BuiltDirectoryExporter`
42574348
- Export generated manifests and BOMs to built directory structure...
42584349

4350+
### `src/core/generation/dataset_generation.py`
4351+
> Programmatic OKH generation from a repository URL or local clone path.
4352+
4353+
Mirrors the CLI ``generate-f...
4354+
42594355
### `src/core/generation/engine.py`
42604356
> Generation Engine for OKH manifest generation.
42614357
@@ -4272,6 +4368,24 @@ This module provides the main orchestration engine t...
42724368

42734369
This class coordinates a...
42744370

4371+
### `src/core/generation/gitlab_instance.py`
4372+
> Self-hosted GitLab instance detection and API base URL helpers.
4373+
4374+
Hosts are trusted as GitLab only wh...
4375+
4376+
**Exports:** normalize_http_url, parse_self_hosted_gitlab_hosts, gitlab_path_has_namespace_and_project, is_allowlisted_self_hosted_gitlab_url, is_gitlab_http_clone_url
4377+
4378+
**Functions:**
4379+
- `normalize_http_url(url)`
4380+
- Match URLRouter-style normalization without importing URLRouter (avoid cycles)....
4381+
- `parse_self_hosted_gitlab_hosts()`
4382+
- Read allowlist from env each time so tests can monkeypatch GITLAB_SELF_HOSTED_HO...
4383+
- `gitlab_path_has_namespace_and_project(path)`
4384+
- `is_allowlisted_self_hosted_gitlab_url(normalized_url)`
4385+
- True if hostname is in GITLAB_SELF_HOSTED_HOSTS and path looks like a project....
4386+
- `is_gitlab_http_clone_url(normalized_url)`
4387+
- True for gitlab.com or allowlisted host with a valid project path (clone/API eli...
4388+
42754389
### `src/core/generation/layers/__init__.py`
42764390
> Generation layers for OKH manifest extraction.
42774391
@@ -4326,9 +4440,11 @@ This layer applies rule-based pattern recogni...
43264440
43274441
This layer uses Large Language Models for advance...
43284442

4329-
**Exports:** LLMGenerationLayer
4443+
**Exports:** ChunkedLLMReduceSchema, LLMGenerationLayer
43304444

43314445
**Classes:**
4446+
- `ChunkedLLMReduceSchema` (inherits: BaseModel)
4447+
- Minimal schema guardrail for chunked reduce output....
43324448
- `LLMGenerationLayer` (inherits: BaseGenerationLayer)
43334449
- LLM Generation Layer using Large Language Models for advanced content analysis.
43344450
...
@@ -4463,6 +4579,35 @@ This module provides URL validation, platform detect...
44634579
44644580
This module provides a LLM provider abstraction ...
44654581

4582+
### `src/core/llm/chunking.py`
4583+
> Core chunking primitives for long-context LLM workflows....
4584+
4585+
**Exports:** TokenEstimator, default_token_estimator, TokenBudget, TokenBudgetPolicy, ChunkingConfig
4586+
4587+
**Classes:**
4588+
- `TokenEstimator` (inherits: Protocol)
4589+
- Protocol for token estimation functions....
4590+
- `TokenBudget`
4591+
- Resolved token budget for a specific request....
4592+
- `TokenBudgetPolicy`
4593+
- Policy inputs used to derive a TokenBudget....
4594+
- `ChunkingConfig`
4595+
- Chunking settings for splitting large input text....
4596+
- `TextChunk`
4597+
- A chunk of source text and its position in the original string....
4598+
4599+
**Functions:**
4600+
- `default_token_estimator(text)`
4601+
- Conservative fallback estimator with no external dependencies.
4602+
4603+
Uses a simple ch...
4604+
- `build_token_budget(policy, request_type, provider)`
4605+
- Build a request-specific token budget and fail fast on impossible budgets....
4606+
- `split_text_into_chunks(text, config, estimate_tokens_fn)`
4607+
- Split text into chunks by token budget with overlap and boundary preferences.
4608+
4609+
T...
4610+
44664611
### `src/core/llm/provider_selection.py`
44674612
> LLM Provider Selection Utility for the Open Hardware Manager.
44684613

docs/CLI/index.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,8 +934,15 @@ You can also explicitly specify the domain using the `--domain` option.
934934
- `--location TEXT` - Filter by location (city, country, or region)
935935
- `--capabilities TEXT` - Comma-separated list of required capabilities
936936
- `--materials TEXT` - Comma-separated list of required materials
937-
- `--min-confidence FLOAT` - Minimum confidence threshold (0.0-1.0, default: 0.7)
937+
- `--min-confidence FLOAT` - Minimum confidence threshold (0.0-1.0, default: 0.3)
938938
- `--max-results INTEGER` - Maximum number of results (default: 10)
939+
- `--max-depth INTEGER` - BOM matching depth (0 = single-level, >0 = nested component matching)
940+
- `--auto-detect-depth` - Auto-enable nested matching when manifest contains nested components
941+
- `--allow-facility-combinations` - Enable aggregated multi-facility matching for manufacturing
942+
- `--max-facilities-per-solution INTEGER` - Cap facilities used in one composite solution (default: 3)
943+
- `--combination-strategy [greedy]` - Composite solver strategy
944+
- `--no-alternative-solutions` - Return only the top composite solution
945+
- `--explain` - Include structured and human-readable per-solution explanations in output
939946
- `--output, -o TEXT` - Output file path
940947
- `--use-llm` - Enable LLM integration for enhanced matching
941948
- `--llm-provider [anthropic|openai|google|azure|local]` - LLM provider
@@ -946,6 +953,9 @@ You can also explicitly specify the domain using the `--domain` option.
946953
- `--table` - Output results in table format
947954
- `--verbose, -v` - Enable verbose output
948955

956+
**Verbose behavior note:**
957+
- In `match requirements`, `--verbose` automatically enables explanation output (equivalent to `--explain`) so diagnostics are consistently shown during interactive debugging.
958+
949959
**Examples:**
950960
```bash
951961
# Match OKH requirements (manufacturing domain)
@@ -969,17 +979,26 @@ ohm match requirements my-design.okh.json --min-confidence 0.9
969979
# Match with LLM enhancement
970980
ohm match requirements my-design.okh.json --use-llm --quality-level professional
971981

982+
# Composite matching across multiple facilities
983+
ohm match requirements my-design.okh.json --allow-facility-combinations --max-facilities-per-solution 3
984+
985+
# Composite matching returning only best solution
986+
ohm match requirements my-design.okh.json --allow-facility-combinations --no-alternative-solutions
987+
972988
# Save results to file
973989
ohm match requirements my-design.okh.json --output matches.json
974990
```
975991

976992
**Output:**
977993
The command displays matching facilities with:
994+
- Rank (`1` = best match)
978995
- Facility name
979996
- **Full facility ID (UUID)** - required for `ohm okw get` command
997+
- Composite detail bundle (`facility_details`) in JSON mode when a solution spans multiple facilities
980998
- Confidence score
981999
- Match type (manufacturing or cooking)
9821000
- Location (if available)
1001+
- Structured summary metadata (`match_summary`, `coverage_gaps`) in JSON mode
9831002

9841003
**Note:** Facility IDs are displayed as full UUIDs. Use the full ID with `ohm okw get` to retrieve facility details.
9851004

docs/api/routes.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,13 @@ The endpoint automatically detects the domain from the input data:
11511151

11521152
// Optional Matching Parameters
11531153
"min_confidence": 0.5,
1154-
"max_results": 10
1154+
"max_results": 10,
1155+
1156+
// Facility-combination controls (API-first)
1157+
"allow_facility_combinations": false,
1158+
"max_facilities_per_solution": 3,
1159+
"return_alternative_solutions": true,
1160+
"combination_strategy": "greedy"
11551161
}
11561162
```
11571163

@@ -1212,12 +1218,20 @@ The endpoint returns a wrapped response with the following structure:
12121218
- `facility`: Complete facility/kitchen information
12131219
- `facility_id`: **Unique identifier** for the facility (required for API operations)
12141220
- `facility_name`: Human-readable facility name
1221+
- `facility_ids`: List of facility IDs participating in the solution (**composite solutions only**)
1222+
- `facility_names`: List of facility names participating in the solution (**composite solutions only**)
1223+
- `facility_details`: List of `{facility_id, facility_name, facility}` objects (**composite solutions only**)
12151224
- `match_type`: Domain type ("manufacturing" or "cooking")
12161225
- `confidence`: Match confidence score (0.0-1.0)
1217-
- `rank`: Solution rank (1 = best match)
1226+
- `rank`: Solution rank (1 = best match, stable after confidence filtering and result limiting)
12181227
- `total_solutions`: Total number of matching solutions found
12191228
- `matching_metrics`: Breakdown of match types
12201229
- `validation_results`: Validation results for each solution
1230+
- `match_summary`: Structured summary object for API consumers (mode, counts, coverage, and combination flags)
1231+
- `coverage_gaps`: Uncovered process requirements, if any
1232+
- `match_summary_text`: Human-readable rendering of `match_summary` (for logs and quick inspection)
1233+
- `match_summary.coverage_gap_counts`: Multiplicity of each uncovered requirement
1234+
- `match_summary.warnings`: Non-fatal warnings (e.g. composite fallback to single-facility matching)
12211235

12221236
**Status:** **Fully Implemented** - **Complete matching engine with Azure Blob Storage integration**
12231237

docs/matching/match-explanation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ When matching requirements to facilities, you can request **per-facility explana
1111
```bash
1212
ohm match requirements my-design.okh.json --explain
1313
```
14+
In current CLI behavior, `--verbose` also enables explanation output automatically for `match requirements`.
1415
Explanations are printed under each facility in table output; in JSON output they appear as `explanation` and `explanation_human` on each solution.
1516

1617
### Manual testing with synthetic data (no server/storage)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ addopts = "-v --tb=short"
5353
asyncio_mode = "strict"
5454
markers = [
5555
"e2e: end-to-end canonical workflow tests",
56+
"integration: integration tests that may require services or seeded data",
5657
"slow: tests that take more than 10 seconds",
5758
"llm: tests requiring LLM API access",
5859
"benchmark: performance benchmark tests",

0 commit comments

Comments
 (0)