qcoder 0.4.0a1__tar.gz → 0.4.0a2__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 (135) hide show
  1. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/CHANGELOG.md +11 -0
  2. {qcoder-0.4.0a1/src/qcoder.egg-info → qcoder-0.4.0a2}/PKG-INFO +8 -5
  3. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/README.md +7 -4
  4. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/docs/architecture.md +3 -1
  5. qcoder-0.4.0a2/docs/model-cards/resource-guidance-local-v0.md +33 -0
  6. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/pyproject.toml +4 -1
  7. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/__init__.py +1 -1
  8. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/run_config.py +1 -17
  9. qcoder-0.4.0a2/src/qcoder/engines/guidance/model_pack.py +353 -0
  10. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/guidance/resource.py +82 -0
  11. qcoder-0.4.0a2/src/qcoder/model_packs/__init__.py +1 -0
  12. qcoder-0.4.0a2/src/qcoder/model_packs/resource_guidance_local_v0.json +183 -0
  13. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/pipelines/analyze.py +2 -29
  14. {qcoder-0.4.0a1 → qcoder-0.4.0a2/src/qcoder.egg-info}/PKG-INFO +8 -5
  15. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder.egg-info/SOURCES.txt +6 -41
  16. qcoder-0.4.0a2/tests/test_guidance_model_pack.py +146 -0
  17. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_resource_guidance.py +56 -0
  18. qcoder-0.4.0a2/tests/test_smoke.py +23 -0
  19. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/__init__.py +0 -16
  20. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/artifact.py +0 -85
  21. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/engine.py +0 -209
  22. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/models.py +0 -62
  23. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/policy.py +0 -45
  24. qcoder-0.4.0a1/src/qcoder/engines/prediction_model/schema_alignment.py +0 -41
  25. qcoder-0.4.0a1/src/qcoder/engines/quantumness/__init__.py +0 -8
  26. qcoder-0.4.0a1/src/qcoder/engines/quantumness/scorer.py +0 -254
  27. qcoder-0.4.0a1/src/qcoder/tools/analyze.py +0 -88
  28. qcoder-0.4.0a1/src/qcoder/tools/analyze_shot_scaling.py +0 -239
  29. qcoder-0.4.0a1/src/qcoder/tools/generate_corpus.py +0 -491
  30. qcoder-0.4.0a1/src/qcoder/tools/harness.py +0 -15
  31. qcoder-0.4.0a1/src/qcoder/tools/inspect_corpus_features.py +0 -273
  32. qcoder-0.4.0a1/src/qcoder/tools/join_runs_features.py +0 -252
  33. qcoder-0.4.0a1/src/qcoder/tools/mirror.py +0 -15
  34. qcoder-0.4.0a1/src/qcoder/tools/predict_baseline.py +0 -347
  35. qcoder-0.4.0a1/src/qcoder/tools/qr_dll_bootstrap.py +0 -31
  36. qcoder-0.4.0a1/src/qcoder/tools/runner.py +0 -15
  37. qcoder-0.4.0a1/src/qcoder/tools/runners/__init__.py +0 -1
  38. qcoder-0.4.0a1/src/qcoder/tools/runners/quantum_rings/__init__.py +0 -1
  39. qcoder-0.4.0a1/src/qcoder/tools/runners/quantum_rings/v12/__init__.py +0 -1
  40. qcoder-0.4.0a1/src/qcoder/tools/runners/quantum_rings/v12/harness.py +0 -1350
  41. qcoder-0.4.0a1/src/qcoder/tools/runners/quantum_rings/v12/mirror.py +0 -459
  42. qcoder-0.4.0a1/src/qcoder/tools/runners/quantum_rings/v12/runner.py +0 -549
  43. qcoder-0.4.0a1/src/qcoder/tools/train_baseline_models.py +0 -619
  44. qcoder-0.4.0a1/src/qcoder/tools/validate_baseline.py +0 -307
  45. qcoder-0.4.0a1/tests/test_analyze_prediction_integration.py +0 -62
  46. qcoder-0.4.0a1/tests/test_analyze_shot_scaling.py +0 -103
  47. qcoder-0.4.0a1/tests/test_generate_corpus.py +0 -113
  48. qcoder-0.4.0a1/tests/test_harness_schema_labels.py +0 -293
  49. qcoder-0.4.0a1/tests/test_inspect_corpus_features.py +0 -118
  50. qcoder-0.4.0a1/tests/test_join_runs_features.py +0 -170
  51. qcoder-0.4.0a1/tests/test_predict_baseline.py +0 -400
  52. qcoder-0.4.0a1/tests/test_prediction_artifact_io.py +0 -55
  53. qcoder-0.4.0a1/tests/test_prediction_fidelity_curve.py +0 -151
  54. qcoder-0.4.0a1/tests/test_prediction_policy.py +0 -35
  55. qcoder-0.4.0a1/tests/test_prediction_schema_alignment.py +0 -40
  56. qcoder-0.4.0a1/tests/test_quantumness_scorer.py +0 -137
  57. qcoder-0.4.0a1/tests/test_smoke.py +0 -20
  58. qcoder-0.4.0a1/tests/test_train_baseline_models.py +0 -158
  59. qcoder-0.4.0a1/tests/test_validate_baseline.py +0 -241
  60. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/LICENSE +0 -0
  61. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/MANIFEST.in +0 -0
  62. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/NOTICE +0 -0
  63. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/setup.cfg +0 -0
  64. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/__main__.py +0 -0
  65. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/cli.py +0 -0
  66. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/__init__.py +0 -0
  67. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/context.py +0 -0
  68. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/qasm2/__init__.py +0 -0
  69. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/qasm2/adjoint_eligibility.py +0 -0
  70. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/qasm2/mirror_build.py +0 -0
  71. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/core/schema.py +0 -0
  72. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/context/__init__.py +0 -0
  73. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/context/bundle.py +0 -0
  74. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/context/markdown.py +0 -0
  75. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/adapters/__init__.py +0 -0
  76. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/adapters/cirq_intake.py +0 -0
  77. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/adapters/pennylane_intake.py +0 -0
  78. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/adapters/qiskit_intake.py +0 -0
  79. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/extractor.py +0 -0
  80. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/features/compute_v0.py +0 -0
  81. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/features/glossary_v0.py +0 -0
  82. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/features/schema_v0.py +0 -0
  83. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/ir.py +0 -0
  84. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/labeling.py +0 -0
  85. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/parsers/__init__.py +0 -0
  86. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/qasm2_regex_parser.py +0 -0
  87. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/cut_profile.py +0 -0
  88. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/depth.py +0 -0
  89. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/entangling_layers.py +0 -0
  90. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/gate_set_stats.py +0 -0
  91. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/interaction_graph.py +0 -0
  92. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/interaction_graph_metrics.py +0 -0
  93. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/feature_extraction/reps/spans.py +0 -0
  94. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/guidance/__init__.py +0 -0
  95. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/guidance/structural_scores.py +0 -0
  96. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/profiles/__init__.py +0 -0
  97. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/profiles/feature_profiles_v0.py +0 -0
  98. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/review/__init__.py +0 -0
  99. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/review/bundle.py +0 -0
  100. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/review/counts_v0.py +0 -0
  101. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/review/markdown.py +0 -0
  102. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/engines/review/qiskit_counts.py +0 -0
  103. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/pipelines/batch.py +0 -0
  104. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/pipelines/context.py +0 -0
  105. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/pipelines/review.py +0 -0
  106. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder/tools/batch.py +0 -0
  107. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder.egg-info/dependency_links.txt +0 -0
  108. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder.egg-info/entry_points.txt +0 -0
  109. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder.egg-info/requires.txt +0 -0
  110. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/src/qcoder.egg-info/top_level.txt +0 -0
  111. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/__init__.py +0 -0
  112. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_adjoint_eligibility.py +0 -0
  113. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_analyze_pipeline.py +0 -0
  114. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_batch_pipeline.py +0 -0
  115. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_cirq_intake.py +0 -0
  116. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_cli_batch_nested_discovery.py +0 -0
  117. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_cli_context_review.py +0 -0
  118. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_cli_help.py +0 -0
  119. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_context_bundle.py +0 -0
  120. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_cut_profile.py +0 -0
  121. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_entangling_layers.py +0 -0
  122. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_examples_smoke.py +0 -0
  123. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_feature_glossary.py +0 -0
  124. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_feature_profiles.py +0 -0
  125. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_gate_set_stats.py +0 -0
  126. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_interaction_graph_metrics.py +0 -0
  127. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_mirror_build.py +0 -0
  128. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_parse_qasm2_text.py +0 -0
  129. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_pennylane_intake.py +0 -0
  130. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_qiskit_intake.py +0 -0
  131. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_review_bundle.py +0 -0
  132. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_review_counts_v0.py +0 -0
  133. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_review_qiskit_counts.py +0 -0
  134. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_schema_stability.py +0 -0
  135. {qcoder-0.4.0a1 → qcoder-0.4.0a2}/tests/test_temporal_spans.py +0 -0
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on common practice for pre-1.0 semantic versioning: **`MAJOR.MINOR.PATCH`** with **`aN`** for alpha prereleases.
6
6
 
7
+ ## 0.4.0a2 (alpha)
8
+
9
+ ### Added
10
+
11
+ - **Local Guidance Pack shadow metadata** — optional **`guidance_metadata`** records the bundled local resource-guidance candidate pack, including pack identity, version/hash metadata, caveats, and **`shadow_guidance`** with **`applied: false`**; deterministic guidance remains authoritative.
12
+
13
+ ### Improved
14
+
15
+ - **Free Single-Run Intelligence** and **BYO LLM** artifact examples clarify that shadow guidance is metadata only.
16
+ - **Release notes** — this alpha has no hosted qCoder compute, no telemetry upload, no qCoder-hosted LLM, no runtime ML dependency, and no optimality, fidelity, runtime, hardware, backend-ranking, or causal-savings claims.
17
+
7
18
  ## 0.4.0a1 (alpha)
8
19
 
9
20
  qCoder **0.4.0a1** adds opt-in derived **feature profiles**, mixed-width **review** checks, and a **5‑minute preflight→review** path.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qcoder
3
- Version: 0.4.0a1
3
+ Version: 0.4.0a2
4
4
  Summary: Quantum circuit analysis and structured feature extraction tools.
5
5
  Author-email: Quantum Ready Solutions <support@qcoder.ai>
6
6
  Maintainer-email: Quantum Ready Solutions <support@qcoder.ai>
@@ -48,7 +48,7 @@ Stable structural **feature vectors** (`schema_version`, `feature_names`, `featu
48
48
  pip install qcoder
49
49
  ```
50
50
 
51
- Pre-release lines on PyPI may look like **`0.4.0a1`**.
51
+ Pre-release lines on PyPI may look like **`0.4.0a2`**.
52
52
 
53
53
  **2. Create a small Bell circuit** as `bell.qasm` (OpenQASM 2), or use the copy in **[`examples/circuits/bell.qasm`](examples/circuits/bell.qasm)** from a clone:
54
54
 
@@ -108,6 +108,9 @@ In real use, **`counts.json`** comes from **your** simulator or hardware pipelin
108
108
 
109
109
  **Examples:** **[`examples/README.md`](examples/README.md)** (Bell QASM + illustrative counts for clones).
110
110
 
111
+ - **Free single-run intelligence** and **BYO LLM artifact workflow:** [`examples/06_single_run_intelligence.md`](examples/06_single_run_intelligence.md), [`examples/07_byo_llm_artifact_pack.md`](examples/07_byo_llm_artifact_pack.md), copy-paste prompt [`examples/prompts/single_run_artifact_to_action.md`](examples/prompts/single_run_artifact_to_action.md).
112
+ - Full walkthrough on the site: [Single-run intelligence with qCoder](https://qcoder.ai/manual/workflows/single-run-intelligence/).
113
+
111
114
  ---
112
115
 
113
116
  ## What qCoder analyzes
@@ -116,7 +119,7 @@ qCoder summarizes **circuit structure** from OpenQASM (and optional framework ex
116
119
 
117
120
  ## Package layout (supported public surface)
118
121
 
119
- For **this release**, treat the **supported surface** as:
122
+ **Current supported public surface:**
120
123
 
121
124
  - **`qcoder analyze`** — single-circuit extraction (human or `--json`).
122
125
  - **`qcoder batch`** — directory batch to **JSONL**.
@@ -130,7 +133,7 @@ For **this release**, treat the **supported surface** as:
130
133
  - **`qcoder[pennylane]`** — optional PennyLane circuit intake into the **same extractor** as OpenQASM.
131
134
  - **Documented feature output** — see [qcoder.ai — Feature reference](https://qcoder.ai/manual/feature-reference/) and `engines/feature_extraction/features/schema_v0.py`; JSON carries a **`schema_version`** alongside named fields.
132
135
 
133
- Other modules under **`src/qcoder`** may exist for prototyping (extra tooling or engines outside the commands above). Unless documented here, **`docs/`**, or **qcoder.ai**, they do **not** share the same stability expectations as the commands and artifact formats listed above.
136
+ The public package contains the documented deterministic free-product surface above.
134
137
 
135
138
  Brief notes live in **`docs/architecture.md`**.
136
139
 
@@ -144,7 +147,7 @@ pip install "qcoder[pennylane]"
144
147
 
145
148
  Machine-readable JSON from **`qcoder analyze --json`** includes a derived **`feature_map`** object (`name → value`) for easier reading. The canonical circuit feature bundle remains the nested **`features`** object (`schema_version`, **`feature_names`**, **`features`**).
146
149
 
147
- Optional **`--guidance`** adds heuristic shot-count and simulator/MPS starting-point suggestions derived from structural features. These suggestions are transparent, non-guaranteed starting points only; qCoder performs no backend execution and includes no telemetry/upload in this flow.
150
+ Optional **`--guidance`** adds heuristic shot-count and simulator/MPS starting-point suggestions derived from structural features. These suggestions are transparent, non-guaranteed starting points only; qCoder performs no backend execution and includes no telemetry/upload in this flow. When a bundled local guidance pack is present, the guidance JSON may also include **`guidance_metadata`** (pack id/version/hash, shadow suggestions, explicit `fallback_used`) for BYO-LLM workflows; **deterministic** `pressure` / `starting_points` remain the user-visible values until a future release explicitly applies pack output.
148
151
 
149
152
  Optional **`--profiles`** adds deterministic **`feature_profiles`** derived from `feature_map` for compact structural taxonomy. This is an additive interpretation layer with its own schema version and does not modify canonical `features` (`schema_version`, `feature_names`, `features`).
150
153
 
@@ -18,7 +18,7 @@ Stable structural **feature vectors** (`schema_version`, `feature_names`, `featu
18
18
  pip install qcoder
19
19
  ```
20
20
 
21
- Pre-release lines on PyPI may look like **`0.4.0a1`**.
21
+ Pre-release lines on PyPI may look like **`0.4.0a2`**.
22
22
 
23
23
  **2. Create a small Bell circuit** as `bell.qasm` (OpenQASM 2), or use the copy in **[`examples/circuits/bell.qasm`](examples/circuits/bell.qasm)** from a clone:
24
24
 
@@ -78,6 +78,9 @@ In real use, **`counts.json`** comes from **your** simulator or hardware pipelin
78
78
 
79
79
  **Examples:** **[`examples/README.md`](examples/README.md)** (Bell QASM + illustrative counts for clones).
80
80
 
81
+ - **Free single-run intelligence** and **BYO LLM artifact workflow:** [`examples/06_single_run_intelligence.md`](examples/06_single_run_intelligence.md), [`examples/07_byo_llm_artifact_pack.md`](examples/07_byo_llm_artifact_pack.md), copy-paste prompt [`examples/prompts/single_run_artifact_to_action.md`](examples/prompts/single_run_artifact_to_action.md).
82
+ - Full walkthrough on the site: [Single-run intelligence with qCoder](https://qcoder.ai/manual/workflows/single-run-intelligence/).
83
+
81
84
  ---
82
85
 
83
86
  ## What qCoder analyzes
@@ -86,7 +89,7 @@ qCoder summarizes **circuit structure** from OpenQASM (and optional framework ex
86
89
 
87
90
  ## Package layout (supported public surface)
88
91
 
89
- For **this release**, treat the **supported surface** as:
92
+ **Current supported public surface:**
90
93
 
91
94
  - **`qcoder analyze`** — single-circuit extraction (human or `--json`).
92
95
  - **`qcoder batch`** — directory batch to **JSONL**.
@@ -100,7 +103,7 @@ For **this release**, treat the **supported surface** as:
100
103
  - **`qcoder[pennylane]`** — optional PennyLane circuit intake into the **same extractor** as OpenQASM.
101
104
  - **Documented feature output** — see [qcoder.ai — Feature reference](https://qcoder.ai/manual/feature-reference/) and `engines/feature_extraction/features/schema_v0.py`; JSON carries a **`schema_version`** alongside named fields.
102
105
 
103
- Other modules under **`src/qcoder`** may exist for prototyping (extra tooling or engines outside the commands above). Unless documented here, **`docs/`**, or **qcoder.ai**, they do **not** share the same stability expectations as the commands and artifact formats listed above.
106
+ The public package contains the documented deterministic free-product surface above.
104
107
 
105
108
  Brief notes live in **`docs/architecture.md`**.
106
109
 
@@ -114,7 +117,7 @@ pip install "qcoder[pennylane]"
114
117
 
115
118
  Machine-readable JSON from **`qcoder analyze --json`** includes a derived **`feature_map`** object (`name → value`) for easier reading. The canonical circuit feature bundle remains the nested **`features`** object (`schema_version`, **`feature_names`**, **`features`**).
116
119
 
117
- Optional **`--guidance`** adds heuristic shot-count and simulator/MPS starting-point suggestions derived from structural features. These suggestions are transparent, non-guaranteed starting points only; qCoder performs no backend execution and includes no telemetry/upload in this flow.
120
+ Optional **`--guidance`** adds heuristic shot-count and simulator/MPS starting-point suggestions derived from structural features. These suggestions are transparent, non-guaranteed starting points only; qCoder performs no backend execution and includes no telemetry/upload in this flow. When a bundled local guidance pack is present, the guidance JSON may also include **`guidance_metadata`** (pack id/version/hash, shadow suggestions, explicit `fallback_used`) for BYO-LLM workflows; **deterministic** `pressure` / `starting_points` remain the user-visible values until a future release explicitly applies pack output.
118
121
 
119
122
  Optional **`--profiles`** adds deterministic **`feature_profiles`** derived from `feature_map` for compact structural taxonomy. This is an additive interpretation layer with its own schema version and does not modify canonical `features` (`schema_version`, `feature_names`, `features`).
120
123
 
@@ -21,10 +21,12 @@ The supported product surface described in **`README.md`** (**Package layout**)
21
21
 
22
22
  The canonical circuit feature schema remains the existing `features` payload (`schema_version`, `feature_names`, `features`) produced by extraction. Guidance/context/review outputs are additive artifact layers and do not change canonical feature schema/version/order.
23
23
 
24
- When requested via CLI flags, qCoder may emit an additional top-level `guidance` block built deterministically from `feature_map`. This guidance is outside the canonical feature schema (`features`) and is intended as transparent heuristic starting points rather than execution-validated recommendations.
24
+ When requested via CLI flags, qCoder may emit an additional top-level `guidance` block built deterministically from `feature_map`. This guidance is outside the canonical feature schema (`features`) and is intended as transparent heuristic starting points rather than execution-validated recommendations. The same block may include **`guidance_metadata`** describing a packaged **shadow-mode** local guidance JSON candidate (read from disk via `importlib.resources`; no network): pack id/version/content hash, optional shadow suggestions, and explicit fallback flags. **Deterministic** MPS `pressure` and `starting_points` stay authoritative in this slice; the pack does not override them yet.
25
25
 
26
26
  qCoder may also emit an optional top-level `feature_profiles` block derived deterministically from `feature_map`. `feature_profiles` is additive, separately versioned (`feature_profiles_schema_version`), and does not alter canonical `features` schema/version/order.
27
27
 
28
28
  The `context` and `review` commands generate deterministic local artifacts (Markdown/JSON) for user-controlled planning and post-run analysis workflows. "LLM-ready/RAG-ready" in this context means users can attach/paste artifacts manually; qCoder itself makes no LLM calls and performs no retrieval, embeddings, network calls, telemetry upload, or database writes. qCoder also does not execute simulators or hardware backends in these flows.
29
29
 
30
30
  Optional framework adapters perform conversion/intake only; they do not execute circuits, simulators, or hardware.
31
+
32
+ The public package contains the documented deterministic free-product surface. Backend-specific runners, learned-prediction experiments, and private analysis prototypes are not part of the public package.
@@ -0,0 +1,33 @@
1
+ # Model card — `resource_guidance_local_v0` (shadow / metadata only)
2
+
3
+ **Status:** Packaged as **candidate** JSON (`0.1.0-candidate`) in the public `qcoder` wheel under `qcoder.model_packs`. **Shadow mode only:** qCoder **does not** apply pack suggestions to `simulation_guidance.mps_bond_dimension.pressure` or `starting_points` in this release slice. Deterministic structural heuristics remain the user-visible source of truth.
4
+
5
+ ## Data scope
6
+
7
+ - **Synthetic / public / qCoder-owned generated variants** only (as declared in the pack `training_data` block).
8
+ - **No** real user telemetry, **no** Pro/private workflow exports, **no** unaudited archive dumps.
9
+
10
+ ## Runtime posture
11
+
12
+ - **Local** package data only (`importlib.resources`); **no** network calls, **no** hosted inference, **no** telemetry upload from this path.
13
+ - **No** runtime ML dependency (plain JSON; stdlib load and validate).
14
+
15
+ ## Non-claims (machine-readable keys also appear in the pack JSON)
16
+
17
+ This pack and any shadow suggestions are **not**:
18
+
19
+ - an optimality proof (`not_optimality_proof`);
20
+ - a fidelity proof (`not_fidelity_proof`);
21
+ - hardware correctness proof (`not_hardware_correctness_proof`);
22
+ - a runtime guarantee (`not_runtime_guarantee`);
23
+ - backend ranking or universal QPU quality scoring (`not_backend_ranking`);
24
+ - causal savings or cost optimality (`not_causal_savings`).
25
+
26
+ ## Behavior in qCoder today
27
+
28
+ - **Deterministic fallback preserved:** `build_resource_guidance` continues to set `pressure` and `starting_points` from structural scores only.
29
+ - **`guidance_metadata`:** additive block on the guidance dict documenting pack id/version/hash, `fallback_used`, and `shadow_guidance` with `applied: false` until a future evaluated release explicitly enables application.
30
+
31
+ ## Promotion (future)
32
+
33
+ Public promotion requires evaluation gates, reproducible labels, and explicit product/API review before any **non-shadow** application of pack outputs.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qcoder"
7
- version = "0.4.0a1"
7
+ version = "0.4.0a2"
8
8
  description = "Quantum circuit analysis and structured feature extraction tools."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -46,6 +46,9 @@ package-dir = {"" = "src"}
46
46
  [tool.setuptools.packages.find]
47
47
  where = ["src"]
48
48
 
49
+ [tool.setuptools.package-data]
50
+ qcoder = ["model_packs/*.json"]
51
+
49
52
  [tool.pytest.ini_options]
50
53
  pythonpath = ["src"]
51
54
 
@@ -1,3 +1,3 @@
1
1
  __all__ = []
2
- __version__ = "0.4.0a1"
2
+ __version__ = "0.4.0a2"
3
3
  file = __file__
@@ -30,7 +30,7 @@ def normalize_precision(x: str | None) -> str:
30
30
  @dataclass(frozen=True)
31
31
  class RunConfig:
32
32
  """
33
- Conditioning variables for runtime/fidelity predictors.
33
+ User-supplied run context for analyze reports.
34
34
 
35
35
  These are NOT circuit-derived features.
36
36
  """
@@ -38,10 +38,6 @@ class RunConfig:
38
38
  backend: str # normalized: "CPU" | "GPU"
39
39
  precision: str # normalized: "single" | "double"
40
40
  threshold: float | None = None # e.g. bond-dimension/threshold conditioning
41
- prediction_artifact_path: str | None = None
42
- prediction_allow_schema_mismatch: bool = False
43
- prediction_fidelity_target: float | None = None
44
- prediction_fidelity_metric: str | None = None
45
41
 
46
42
  @staticmethod
47
43
  def from_raw(
@@ -50,10 +46,6 @@ class RunConfig:
50
46
  backend: str | None = None,
51
47
  precision: str | None = None,
52
48
  threshold: float | None = None,
53
- prediction_artifact_path: str | None = None,
54
- prediction_allow_schema_mismatch: bool | None = None,
55
- prediction_fidelity_target: float | None = None,
56
- prediction_fidelity_metric: str | None = None,
57
49
  ) -> "RunConfig":
58
50
  # accept processor OR backend as the same input channel
59
51
  raw = processor if processor is not None else backend
@@ -65,10 +57,6 @@ class RunConfig:
65
57
  backend=normalize_backend(raw or backend),
66
58
  precision=normalize_precision(precision),
67
59
  threshold=float(threshold) if threshold is not None else None,
68
- prediction_artifact_path=prediction_artifact_path,
69
- prediction_allow_schema_mismatch=prediction_allow_schema_mismatch or False,
70
- prediction_fidelity_target=prediction_fidelity_target,
71
- prediction_fidelity_metric=prediction_fidelity_metric,
72
60
  )
73
61
 
74
62
  def to_dict(self) -> dict:
@@ -77,8 +65,4 @@ class RunConfig:
77
65
  "backend": self.backend,
78
66
  "precision": self.precision,
79
67
  "threshold": self.threshold,
80
- "prediction_artifact_path": self.prediction_artifact_path,
81
- "prediction_allow_schema_mismatch": self.prediction_allow_schema_mismatch,
82
- "prediction_fidelity_target": self.prediction_fidelity_target,
83
- "prediction_fidelity_metric": self.prediction_fidelity_metric,
84
68
  }
@@ -0,0 +1,353 @@
1
+ """Local resource guidance JSON pack: load, validate, and shadow evaluation (stdlib only, no network)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from dataclasses import dataclass
8
+ from importlib import resources
9
+ from typing import Any, Mapping
10
+
11
+ PACK_RESOURCE = "resource_guidance_local_v0.json"
12
+ PACK_PACKAGE = "qcoder.model_packs"
13
+
14
+ ALLOWED_OPS = frozenset({"<", "<=", "==", ">=", ">"})
15
+ REQUIRED_NON_CLAIMS = frozenset(
16
+ {
17
+ "not_optimality_proof",
18
+ "not_fidelity_proof",
19
+ "not_hardware_correctness_proof",
20
+ "not_runtime_guarantee",
21
+ "not_backend_ranking",
22
+ "not_causal_savings",
23
+ }
24
+ )
25
+ EXPECTED_OUTPUT_MAPPING = {
26
+ "mps_pressure": "simulation_guidance.mps_bond_dimension.pressure",
27
+ "mps_ladder": "simulation_guidance.mps_bond_dimension.starting_points",
28
+ }
29
+ REQUIRED_TOP_LEVEL = (
30
+ "model_pack_schema_version",
31
+ "model_pack_id",
32
+ "model_pack_version",
33
+ "target_feature_schema_versions",
34
+ "targets",
35
+ "rule_evaluation",
36
+ "condition_logic",
37
+ "no_match_behavior",
38
+ "training_data",
39
+ "features",
40
+ "support_bounds",
41
+ "outputs",
42
+ "output_mapping",
43
+ "rules",
44
+ "fallback",
45
+ "non_claims",
46
+ )
47
+ EXPECTED_FEATURES = frozenset(
48
+ {
49
+ "n_qubits",
50
+ "n_cbits",
51
+ "n_measure_ops",
52
+ "n_2q_gate_ops",
53
+ "n_param_ops",
54
+ "real_depth",
55
+ "entangling_depth",
56
+ "n_entangling_layers",
57
+ "cut_max",
58
+ "cut_mean",
59
+ "cut_entropy",
60
+ "n_active_cuts",
61
+ "span_avg",
62
+ "span_max",
63
+ "span_long_range_ratio",
64
+ "ig_edge_density",
65
+ "ig_avg_degree",
66
+ "ig_is_connected",
67
+ }
68
+ )
69
+
70
+
71
+ @dataclass(frozen=True)
72
+ class ResourceGuidancePack:
73
+ """Validated resource guidance pack (shadow / metadata only in v0)."""
74
+
75
+ model_pack_id: str
76
+ model_pack_version: str
77
+ model_pack_schema_version: str
78
+ sha256_hex: str
79
+ data: dict[str, Any]
80
+
81
+
82
+ def compute_pack_sha256(raw: bytes) -> str:
83
+ return hashlib.sha256(raw).hexdigest()
84
+
85
+
86
+ def _feat(feature_map: Mapping[str, Any], key: str) -> float:
87
+ value = feature_map.get(key, 0.0)
88
+ try:
89
+ return float(value)
90
+ except (TypeError, ValueError):
91
+ return 0.0
92
+
93
+
94
+ def _float(x: Any) -> float | None:
95
+ try:
96
+ return float(x)
97
+ except (TypeError, ValueError):
98
+ return None
99
+
100
+
101
+ def _condition_matches(feature_map: Mapping[str, Any], cond: Mapping[str, Any]) -> bool:
102
+ feat = cond.get("feature")
103
+ op = cond.get("op")
104
+ val = cond.get("value")
105
+ if feat not in EXPECTED_FEATURES or op not in ALLOWED_OPS:
106
+ return False
107
+ lhs = _feat(feature_map, str(feat))
108
+ rhs = _float(val)
109
+ if rhs is None:
110
+ return False
111
+ if op == "<":
112
+ return lhs < rhs
113
+ if op == "<=":
114
+ return lhs <= rhs
115
+ if op == "==":
116
+ return lhs == rhs
117
+ if op == ">=":
118
+ return lhs >= rhs
119
+ if op == ">":
120
+ return lhs > rhs
121
+ return False
122
+
123
+
124
+ def _trivial_catchall(cond: Mapping[str, Any], *, n_qubits_min: float) -> bool:
125
+ feat = cond.get("feature")
126
+ op = cond.get("op")
127
+ rhs = _float(cond.get("value"))
128
+ if rhs is None or feat not in EXPECTED_FEATURES or op not in ALLOWED_OPS:
129
+ return False
130
+ if feat == "n_qubits" and op == ">=":
131
+ if rhs <= 0:
132
+ return True
133
+ if rhs <= n_qubits_min:
134
+ return True
135
+ if op == ">=" and rhs <= 0:
136
+ return True
137
+ return False
138
+
139
+
140
+ def validate_resource_guidance_pack(data: Mapping[str, Any]) -> list[str]:
141
+ """Return a list of validation errors; empty means the pack is acceptable."""
142
+ errors: list[str] = []
143
+
144
+ if not isinstance(data, dict):
145
+ return ["root must be a JSON object"]
146
+
147
+ for key in REQUIRED_TOP_LEVEL:
148
+ if key not in data:
149
+ errors.append(f"missing top-level key: {key}")
150
+
151
+ if data.get("model_pack_schema_version") != "resource_guidance_pack.v0":
152
+ errors.append("model_pack_schema_version must be resource_guidance_pack.v0")
153
+
154
+ targets = data.get("targets")
155
+ if targets != ["mps_pressure", "mps_bond_ladder"]:
156
+ errors.append("targets must be exactly ['mps_pressure', 'mps_bond_ladder']")
157
+
158
+ if data.get("rule_evaluation") != "first_match":
159
+ errors.append("rule_evaluation must be 'first_match'")
160
+
161
+ if data.get("condition_logic") != "all":
162
+ errors.append("condition_logic must be 'all'")
163
+
164
+ if data.get("no_match_behavior") != "fallback_deterministic":
165
+ errors.append("no_match_behavior must be 'fallback_deterministic'")
166
+
167
+ om = data.get("output_mapping")
168
+ if om != EXPECTED_OUTPUT_MAPPING:
169
+ errors.append("output_mapping must match expected public guidance paths")
170
+
171
+ nc = data.get("non_claims", [])
172
+ if not isinstance(nc, list) or frozenset(nc) != REQUIRED_NON_CLAIMS or len(nc) != len(REQUIRED_NON_CLAIMS):
173
+ errors.append("non_claims must contain exactly the required non-claim keys")
174
+
175
+ feats = data.get("features", [])
176
+ if not isinstance(feats, list) or frozenset(feats) != EXPECTED_FEATURES or len(feats) != len(EXPECTED_FEATURES):
177
+ errors.append("features must be the expected unique structural set (18 names)")
178
+
179
+ sb = data.get("support_bounds", {})
180
+ nqb = sb.get("n_qubits", {}) if isinstance(sb, dict) else {}
181
+ n_min = _float(nqb.get("min")) if isinstance(nqb, dict) else None
182
+ n_max = _float(nqb.get("max")) if isinstance(nqb, dict) else None
183
+ if n_min is None or n_max is None:
184
+ errors.append("support_bounds.n_qubits must include numeric min and max")
185
+ n_qubits_min = 1.0
186
+ else:
187
+ n_qubits_min = float(n_min)
188
+
189
+ ladders = data.get("outputs", {}).get("mps_ladders", {}) if isinstance(data.get("outputs"), dict) else {}
190
+ if not isinstance(ladders, dict):
191
+ errors.append("outputs.mps_ladders must be an object")
192
+ else:
193
+ for label in ("low", "medium", "high"):
194
+ if label not in ladders or not isinstance(ladders[label], list):
195
+ errors.append(f"outputs.mps_ladders.{label} must be a non-empty array")
196
+
197
+ ladder_keys = frozenset(ladders.keys()) if isinstance(ladders, dict) else frozenset()
198
+
199
+ rules = data.get("rules", [])
200
+ if not isinstance(rules, list) or len(rules) < 1:
201
+ errors.append("rules must be a non-empty array")
202
+ return errors
203
+
204
+ for i, rule in enumerate(rules):
205
+ if not isinstance(rule, dict):
206
+ errors.append(f"rules[{i}] must be an object")
207
+ continue
208
+ for rk in ("rule_id", "conditions", "output"):
209
+ if rk not in rule:
210
+ errors.append(f"rules[{i}] missing {rk}")
211
+ conds = rule.get("conditions", [])
212
+ if isinstance(conds, list) and len(conds) == 1 and isinstance(conds[0], dict):
213
+ if _trivial_catchall(conds[0], n_qubits_min=n_qubits_min):
214
+ errors.append(
215
+ f"rules[{i}] is a trivial catch-all (forbidden for public guidance packs); "
216
+ "use no_match_behavior fallback instead"
217
+ )
218
+ out = rule.get("output", {})
219
+ if isinstance(out, dict):
220
+ if out.get("mps_pressure") not in ladder_keys:
221
+ errors.append(f"rules[{i}].output.mps_pressure must be a ladder label")
222
+ if out.get("mps_ladder") not in ladder_keys:
223
+ errors.append(f"rules[{i}].output.mps_ladder must be a ladder label")
224
+ if not isinstance(conds, list) or not conds:
225
+ errors.append(f"rules[{i}].conditions must be a non-empty array")
226
+ continue
227
+ for j, c in enumerate(conds):
228
+ if not isinstance(c, dict):
229
+ errors.append(f"rules[{i}].conditions[{j}] must be an object")
230
+ continue
231
+ if c.get("op") not in ALLOWED_OPS:
232
+ errors.append(f"rules[{i}].conditions[{j}].op is not an allowed op")
233
+ if c.get("feature") not in EXPECTED_FEATURES:
234
+ errors.append(f"rules[{i}].conditions[{j}].feature is not a known feature")
235
+
236
+ return errors
237
+
238
+
239
+ def load_resource_guidance_pack() -> ResourceGuidancePack | None:
240
+ """Load the bundled resource guidance pack from package data, or None if missing/invalid."""
241
+ try:
242
+ root = resources.files(PACK_PACKAGE)
243
+ path = root.joinpath(PACK_RESOURCE)
244
+ raw = path.read_bytes()
245
+ except (OSError, FileNotFoundError, TypeError, ValueError):
246
+ return None
247
+
248
+ try:
249
+ data = json.loads(raw.decode("utf-8"))
250
+ except (UnicodeDecodeError, json.JSONDecodeError):
251
+ return None
252
+
253
+ if validate_resource_guidance_pack(data):
254
+ return None
255
+
256
+ if not isinstance(data, dict):
257
+ return None
258
+
259
+ digest = compute_pack_sha256(raw)
260
+ return ResourceGuidancePack(
261
+ model_pack_id=str(data.get("model_pack_id", "")),
262
+ model_pack_version=str(data.get("model_pack_version", "")),
263
+ model_pack_schema_version=str(data.get("model_pack_schema_version", "")),
264
+ sha256_hex=digest,
265
+ data=dict(data),
266
+ )
267
+
268
+
269
+ def evaluate_resource_guidance_pack_shadow(
270
+ features: Mapping[str, Any],
271
+ pack: ResourceGuidancePack,
272
+ *,
273
+ feature_schema_version: str,
274
+ ) -> dict[str, Any]:
275
+ """
276
+ First-match shadow evaluation: suggest pack ladder/pressure without applying to public guidance.
277
+
278
+ Out-of-support ``n_qubits`` or unsupported feature schema version yields no match
279
+ (caller should keep deterministic guidance).
280
+ """
281
+ tvers = pack.data.get("target_feature_schema_versions", [])
282
+ if not isinstance(tvers, list) or feature_schema_version not in tvers:
283
+ return {
284
+ "matched_rule_id": None,
285
+ "suggested_mps_pressure": None,
286
+ "suggested_mps_ladder": None,
287
+ "suggested_starting_points": None,
288
+ "no_match_reason": "unsupported_feature_schema",
289
+ }
290
+
291
+ sb = pack.data.get("support_bounds", {})
292
+ nqb = sb.get("n_qubits", {}) if isinstance(sb, dict) else {}
293
+ n_min = _float(nqb.get("min")) if isinstance(nqb, dict) else None
294
+ n_max = _float(nqb.get("max")) if isinstance(nqb, dict) else None
295
+ nq = _feat(features, "n_qubits")
296
+ if n_min is not None and nq < n_min:
297
+ return {
298
+ "matched_rule_id": None,
299
+ "suggested_mps_pressure": None,
300
+ "suggested_mps_ladder": None,
301
+ "suggested_starting_points": None,
302
+ "no_match_reason": "out_of_support_bounds",
303
+ }
304
+ if n_max is not None and nq > n_max:
305
+ return {
306
+ "matched_rule_id": None,
307
+ "suggested_mps_pressure": None,
308
+ "suggested_mps_ladder": None,
309
+ "suggested_starting_points": None,
310
+ "no_match_reason": "out_of_support_bounds",
311
+ }
312
+
313
+ rules = pack.data.get("rules", [])
314
+ ladders = pack.data.get("outputs", {}).get("mps_ladders", {})
315
+ if not isinstance(rules, list) or not isinstance(ladders, dict):
316
+ return {
317
+ "matched_rule_id": None,
318
+ "suggested_mps_pressure": None,
319
+ "suggested_mps_ladder": None,
320
+ "suggested_starting_points": None,
321
+ "no_match_reason": "invalid_pack_shape",
322
+ }
323
+
324
+ for rule in rules:
325
+ if not isinstance(rule, dict):
326
+ continue
327
+ conds = rule.get("conditions", [])
328
+ if not isinstance(conds, list) or not conds:
329
+ continue
330
+ if not all(isinstance(c, dict) and _condition_matches(features, c) for c in conds):
331
+ continue
332
+ out = rule.get("output", {})
333
+ if not isinstance(out, dict):
334
+ continue
335
+ ladder_key = out.get("mps_ladder")
336
+ sp = ladders.get(ladder_key) if isinstance(ladder_key, str) else None
337
+ if not isinstance(sp, list):
338
+ sp = None
339
+ return {
340
+ "matched_rule_id": rule.get("rule_id"),
341
+ "suggested_mps_pressure": out.get("mps_pressure"),
342
+ "suggested_mps_ladder": ladder_key,
343
+ "suggested_starting_points": list(sp) if sp is not None else None,
344
+ "no_match_reason": None,
345
+ }
346
+
347
+ return {
348
+ "matched_rule_id": None,
349
+ "suggested_mps_pressure": None,
350
+ "suggested_mps_ladder": None,
351
+ "suggested_starting_points": None,
352
+ "no_match_reason": "no_matching_rule",
353
+ }