qcoder 0.5.0a5__tar.gz → 0.5.0a7__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.
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/CHANGELOG.md +24 -0
- {qcoder-0.5.0a5/src/qcoder.egg-info → qcoder-0.5.0a7}/PKG-INFO +23 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/README.md +20 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/pyproject.toml +3 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/__init__.py +1 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/cli.py +131 -28
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/run_config.py +6 -0
- qcoder-0.5.0a7/src/qcoder/core/share_safe.py +278 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/context/bundle.py +2 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/context/markdown.py +7 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/qasm2_regex_parser.py +1 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/review/bundle.py +4 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/review/markdown.py +7 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/explorer/derived_evidence.py +1 -1
- qcoder-0.5.0a7/src/qcoder/mcp/__init__.py +5 -0
- qcoder-0.5.0a7/src/qcoder/mcp/server.py +87 -0
- qcoder-0.5.0a7/src/qcoder/mcp/tools.py +334 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pipelines/analyze.py +12 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pipelines/context.py +4 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pipelines/review.py +14 -2
- {qcoder-0.5.0a5 → qcoder-0.5.0a7/src/qcoder.egg-info}/PKG-INFO +23 -1
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder.egg-info/SOURCES.txt +4 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/LICENSE +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/MANIFEST.in +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/NOTICE +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/setup.cfg +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/__main__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/context.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/qasm2/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/qasm2/adjoint_eligibility.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/qasm2/mirror_build.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/core/schema.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/context/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/adapters/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/adapters/cirq_intake.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/adapters/pennylane_intake.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/adapters/qiskit_intake.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/extractor.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/features/compute_v0.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/features/glossary_v0.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/features/schema_v0.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/ir.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/labeling.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/parsers/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/cut_profile.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/depth.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/entangling_layers.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/gate_set_stats.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/interaction_graph.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/interaction_graph_metrics.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/feature_extraction/reps/spans.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/guidance/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/guidance/model_pack.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/guidance/resource.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/guidance/structural_scores.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/profiles/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/profiles/feature_profiles_v0.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/review/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/review/counts_v0.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/engines/review/qiskit_counts.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/explorer/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/model_packs/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/model_packs/resource_guidance_local_v0.json +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pipelines/batch.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pro_preview/__init__.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pro_preview/client.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pro_preview/config.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pro_preview/errors.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/pro_preview/manifest.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder/tools/batch.py +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder.egg-info/dependency_links.txt +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder.egg-info/entry_points.txt +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder.egg-info/requires.txt +0 -0
- {qcoder-0.5.0a5 → qcoder-0.5.0a7}/src/qcoder.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 0.5.0a7
|
|
5
|
+
|
|
6
|
+
- Add local read-only qCoder MCP for Cursor-oriented Explorer Launch workflows.
|
|
7
|
+
- Add MCP tools for local circuit analysis, context-pack generation, counts review, bounded findings, claim boundaries, next checks, and share-safe artifact sanitization.
|
|
8
|
+
- Document the Evidence-Grounded Coding Loop and preserve the manual artifact handoff as launch-required even when local MCP is available.
|
|
9
|
+
- Harden Windows-created inputs by accepting UTF-8 BOM in QASM and JSON paths used by local analysis/review.
|
|
10
|
+
- Improve `qcoder review` error guidance for malformed JSON and Qiskit counts input.
|
|
11
|
+
- Add MCP, share-safe, claim-boundary, and Windows/QASM/Qiskit tests plus release-check MCP stdio rehearsal.
|
|
12
|
+
- Preserve launch boundaries: no public hosted MCP claim, no live service calls from MCP, no token requirement, no autonomous code modification, no QPU/simulator submission, and no runtime/fidelity/backend/QPU/correctness/advantage claims.
|
|
13
|
+
- This is release-candidate preparation only until separately published.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## 0.5.0a6
|
|
17
|
+
|
|
18
|
+
- Add share-safe / redacted artifact mode for artifacts intended for ChatGPT, Cursor, email, GitHub issues, or support threads.
|
|
19
|
+
- Add `--share-safe` / `--redact` to OSS artifact commands and Explorer evidence file output.
|
|
20
|
+
- Emit share-safety metadata in JSON artifacts: `share_safe`, `redactions_applied`, `raw_qasm_included`, `local_paths_included`, and `tokens_included`.
|
|
21
|
+
- Add a visible share-safe note to Markdown artifacts.
|
|
22
|
+
- Fix Windows free-text path redaction, including `C:\Users\...` paths, Windows forward-slash paths, UNC paths, home-relative paths, Linux home paths, and WSL-mounted Windows paths.
|
|
23
|
+
- Preserve normal rich local artifacts by default; share-safe mode is opt-in.
|
|
24
|
+
- Share-safe mode is designed for safer sharing and users should still review artifacts before sharing. It is not a privacy guarantee.
|
|
25
|
+
- Remaining P1 hardening: forward-slash UNC variants, broader Linux root patterns, independent post-scan hardening, and expanded docs wording.
|
|
26
|
+
|
|
27
|
+
|
|
4
28
|
## 0.5.0a5
|
|
5
29
|
|
|
6
30
|
- Add `qcoder explorer evidence` as the primary Explorer Beta guided-evidence surface.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qcoder
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.0a7
|
|
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>
|
|
@@ -15,6 +15,8 @@ Classifier: Intended Audience :: Science/Research
|
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
20
|
Requires-Python: >=3.11
|
|
19
21
|
Description-Content-Type: text/markdown
|
|
20
22
|
License-File: LICENSE
|
|
@@ -40,6 +42,7 @@ The current public local path is **qCoder OSS**. OSS commands run locally and do
|
|
|
40
42
|
- `qcoder batch`
|
|
41
43
|
- `qcoder context`
|
|
42
44
|
- `qcoder review`
|
|
45
|
+
- `qcoder mcp` (local read-only Cursor MCP tools)
|
|
43
46
|
- `qcoder explorer` (Explorer Beta account-backed status/demo/evidence checks)
|
|
44
47
|
- `qcoder student` (temporary compatibility alias for Explorer Beta)
|
|
45
48
|
- `qcoder pro` (archived pilot/bootstrap client contract; non-confidential local plumbing only, not a current public product path)
|
|
@@ -77,6 +80,24 @@ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md p
|
|
|
77
80
|
qcoder review --counts-json counts.json --format qiskit_counts --preflight-json preflight.context.json --out-json execution.review.json --out-md execution.review.md
|
|
78
81
|
```
|
|
79
82
|
|
|
83
|
+
For artifacts you intend to paste into ChatGPT, Cursor, email, GitHub issues, or support threads, add `--share-safe`:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
qcoder analyze path/to/circuit.qasm --json --share-safe
|
|
87
|
+
qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md preflight.context.md --share-safe
|
|
88
|
+
qcoder review --counts-json counts.json --format qiskit_counts --preflight-json preflight.context.json --out-json execution.review.json --out-md execution.review.md --share-safe
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Share-safe mode is designed for safer sharing: it redacts local paths and token/header-like strings, adds `share_safe=true`, and marks raw QASM/local paths/tokens as not included. Review artifacts before sharing; this is not a guarantee that all sensitive project content has been removed.
|
|
92
|
+
|
|
93
|
+
Local Cursor MCP:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
qcoder mcp serve
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The MCP server uses explicit user-selected local inputs only. It reads, inspects, explains, bounds, and recommends; it does not execute circuits, modify user code, read arbitrary files, call live services, or require tokens. See [Explorer Evidence-Grounded Coding Loop](examples/08_explorer_evidence_grounded_coding_loop.md) for the manual artifact loop, Cursor MCP setup, and claim boundaries.
|
|
100
|
+
|
|
80
101
|
Explorer Beta compatibility checks and archived Pro bootstrap:
|
|
81
102
|
|
|
82
103
|
```bash
|
|
@@ -85,6 +106,7 @@ qcoder explorer demo
|
|
|
85
106
|
qcoder explorer evidence
|
|
86
107
|
qcoder explorer evidence --qasm path/to/circuit.qasm
|
|
87
108
|
qcoder explorer evidence --context-json preflight.context.json
|
|
109
|
+
qcoder explorer evidence --qasm path/to/circuit.qasm --out-json explorer.json --out-md explorer.md --share-safe
|
|
88
110
|
qcoder pro --help
|
|
89
111
|
```
|
|
90
112
|
|
|
@@ -10,6 +10,7 @@ The current public local path is **qCoder OSS**. OSS commands run locally and do
|
|
|
10
10
|
- `qcoder batch`
|
|
11
11
|
- `qcoder context`
|
|
12
12
|
- `qcoder review`
|
|
13
|
+
- `qcoder mcp` (local read-only Cursor MCP tools)
|
|
13
14
|
- `qcoder explorer` (Explorer Beta account-backed status/demo/evidence checks)
|
|
14
15
|
- `qcoder student` (temporary compatibility alias for Explorer Beta)
|
|
15
16
|
- `qcoder pro` (archived pilot/bootstrap client contract; non-confidential local plumbing only, not a current public product path)
|
|
@@ -47,6 +48,24 @@ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md p
|
|
|
47
48
|
qcoder review --counts-json counts.json --format qiskit_counts --preflight-json preflight.context.json --out-json execution.review.json --out-md execution.review.md
|
|
48
49
|
```
|
|
49
50
|
|
|
51
|
+
For artifacts you intend to paste into ChatGPT, Cursor, email, GitHub issues, or support threads, add `--share-safe`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
qcoder analyze path/to/circuit.qasm --json --share-safe
|
|
55
|
+
qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md preflight.context.md --share-safe
|
|
56
|
+
qcoder review --counts-json counts.json --format qiskit_counts --preflight-json preflight.context.json --out-json execution.review.json --out-md execution.review.md --share-safe
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Share-safe mode is designed for safer sharing: it redacts local paths and token/header-like strings, adds `share_safe=true`, and marks raw QASM/local paths/tokens as not included. Review artifacts before sharing; this is not a guarantee that all sensitive project content has been removed.
|
|
60
|
+
|
|
61
|
+
Local Cursor MCP:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
qcoder mcp serve
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The MCP server uses explicit user-selected local inputs only. It reads, inspects, explains, bounds, and recommends; it does not execute circuits, modify user code, read arbitrary files, call live services, or require tokens. See [Explorer Evidence-Grounded Coding Loop](examples/08_explorer_evidence_grounded_coding_loop.md) for the manual artifact loop, Cursor MCP setup, and claim boundaries.
|
|
68
|
+
|
|
50
69
|
Explorer Beta compatibility checks and archived Pro bootstrap:
|
|
51
70
|
|
|
52
71
|
```bash
|
|
@@ -55,6 +74,7 @@ qcoder explorer demo
|
|
|
55
74
|
qcoder explorer evidence
|
|
56
75
|
qcoder explorer evidence --qasm path/to/circuit.qasm
|
|
57
76
|
qcoder explorer evidence --context-json preflight.context.json
|
|
77
|
+
qcoder explorer evidence --qasm path/to/circuit.qasm --out-json explorer.json --out-md explorer.md --share-safe
|
|
58
78
|
qcoder pro --help
|
|
59
79
|
```
|
|
60
80
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qcoder"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.0a7"
|
|
8
8
|
description = "Quantum circuit analysis and structured feature extraction tools."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -23,6 +23,8 @@ classifiers = [
|
|
|
23
23
|
"Topic :: Scientific/Engineering",
|
|
24
24
|
"Programming Language :: Python :: 3",
|
|
25
25
|
"Programming Language :: Python :: 3 :: Only",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
26
28
|
]
|
|
27
29
|
dependencies = ["numpy"]
|
|
28
30
|
|
|
@@ -3,11 +3,17 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
import json
|
|
5
5
|
import sys
|
|
6
|
+
from json import JSONDecodeError
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
|
|
8
9
|
from qcoder.pipelines.analyze import analyze_qasm
|
|
9
10
|
from qcoder.pipelines.context import write_preflight_context
|
|
10
11
|
from qcoder.pipelines.review import write_execution_review
|
|
12
|
+
from qcoder.core.share_safe import (
|
|
13
|
+
make_share_safe_payload,
|
|
14
|
+
render_share_safe_note,
|
|
15
|
+
render_share_safe_provenance,
|
|
16
|
+
)
|
|
11
17
|
from qcoder.explorer.derived_evidence import (
|
|
12
18
|
ExplorerDerivedEvidenceRequestError,
|
|
13
19
|
build_derived_evidence_request_from_context_json,
|
|
@@ -100,6 +106,13 @@ def _cmd_analyze(argv: list[str]) -> int:
|
|
|
100
106
|
help="Include derived feature_profiles in JSON output (requires --json for analyze)",
|
|
101
107
|
)
|
|
102
108
|
p.add_argument("--json", action="store_true", help="Emit machine-readable JSON")
|
|
109
|
+
p.add_argument(
|
|
110
|
+
"--share-safe",
|
|
111
|
+
"--redact",
|
|
112
|
+
dest="share_safe",
|
|
113
|
+
action="store_true",
|
|
114
|
+
help="Redact local paths and sensitive runtime details in JSON output intended for sharing.",
|
|
115
|
+
)
|
|
103
116
|
args = p.parse_args(argv)
|
|
104
117
|
|
|
105
118
|
if args.profiles and not args.json:
|
|
@@ -120,9 +133,12 @@ def _cmd_analyze(argv: list[str]) -> int:
|
|
|
120
133
|
)
|
|
121
134
|
|
|
122
135
|
if args.json:
|
|
136
|
+
payload = report.to_json_dict(include_guidance=args.guidance, include_profiles=args.profiles)
|
|
137
|
+
if args.share_safe:
|
|
138
|
+
payload = make_share_safe_payload(payload)
|
|
123
139
|
print(
|
|
124
140
|
json.dumps(
|
|
125
|
-
|
|
141
|
+
payload,
|
|
126
142
|
indent=2,
|
|
127
143
|
sort_keys=True,
|
|
128
144
|
)
|
|
@@ -131,7 +147,9 @@ def _cmd_analyze(argv: list[str]) -> int:
|
|
|
131
147
|
|
|
132
148
|
ex = report.example
|
|
133
149
|
rc = report.run_config
|
|
134
|
-
print(f"file: {ex.qasm_path}")
|
|
150
|
+
print(f"file: {'<redacted-local-path>' if args.share_safe else ex.qasm_path}")
|
|
151
|
+
if args.share_safe:
|
|
152
|
+
print("share_safe: true")
|
|
135
153
|
print(f"format: {ex.ir.source_format}")
|
|
136
154
|
if ex.name:
|
|
137
155
|
print(f"name: {ex.name}")
|
|
@@ -218,6 +236,13 @@ def _cmd_context(argv: list[str]) -> int:
|
|
|
218
236
|
action="store_true",
|
|
219
237
|
help="Include full feature glossary/appendix in context artifacts (default: selected structural features only)",
|
|
220
238
|
)
|
|
239
|
+
p.add_argument(
|
|
240
|
+
"--share-safe",
|
|
241
|
+
"--redact",
|
|
242
|
+
dest="share_safe",
|
|
243
|
+
action="store_true",
|
|
244
|
+
help="Write artifacts designed for safer sharing by redacting local paths and sensitive runtime details.",
|
|
245
|
+
)
|
|
221
246
|
args = p.parse_args(argv)
|
|
222
247
|
|
|
223
248
|
write_preflight_context(
|
|
@@ -229,9 +254,12 @@ def _cmd_context(argv: list[str]) -> int:
|
|
|
229
254
|
include_full_features=args.full_features,
|
|
230
255
|
circuit_id=args.circuit_id,
|
|
231
256
|
circuit_name=args.circuit_name,
|
|
257
|
+
share_safe=args.share_safe,
|
|
232
258
|
)
|
|
233
|
-
|
|
234
|
-
|
|
259
|
+
json_label = "<redacted-local-path>" if args.share_safe else args.out_json
|
|
260
|
+
md_label = "<redacted-local-path>" if args.share_safe else args.out_md
|
|
261
|
+
print(f"Wrote preflight context JSON to {json_label}", file=sys.stderr)
|
|
262
|
+
print(f"Wrote preflight context Markdown to {md_label}", file=sys.stderr)
|
|
235
263
|
return 0
|
|
236
264
|
|
|
237
265
|
|
|
@@ -248,17 +276,66 @@ def _cmd_review(argv: list[str]) -> int:
|
|
|
248
276
|
p.add_argument("--preflight-json", default=None, help="Optional preflight context JSON path for linkage/checks")
|
|
249
277
|
p.add_argument("--out-json", required=True, help="Output execution review JSON path")
|
|
250
278
|
p.add_argument("--out-md", required=True, help="Output execution review Markdown path")
|
|
279
|
+
p.add_argument(
|
|
280
|
+
"--share-safe",
|
|
281
|
+
"--redact",
|
|
282
|
+
dest="share_safe",
|
|
283
|
+
action="store_true",
|
|
284
|
+
help="Write artifacts designed for safer sharing by redacting local paths and sensitive runtime details.",
|
|
285
|
+
)
|
|
251
286
|
args = p.parse_args(argv)
|
|
252
287
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
288
|
+
try:
|
|
289
|
+
write_execution_review(
|
|
290
|
+
counts_json=args.counts_json,
|
|
291
|
+
counts_format=args.counts_format,
|
|
292
|
+
preflight_json=args.preflight_json,
|
|
293
|
+
out_json=args.out_json,
|
|
294
|
+
out_md=args.out_md,
|
|
295
|
+
share_safe=args.share_safe,
|
|
296
|
+
)
|
|
297
|
+
except JSONDecodeError as exc:
|
|
298
|
+
print(
|
|
299
|
+
f"qcoder review: input JSON could not be parsed at line {exc.lineno}, column {exc.colno}. "
|
|
300
|
+
"Check that the counts/preflight file is UTF-8 JSON.",
|
|
301
|
+
file=sys.stderr,
|
|
302
|
+
)
|
|
303
|
+
return 2
|
|
304
|
+
except ValueError as exc:
|
|
305
|
+
print(
|
|
306
|
+
f"qcoder review: {exc}. For Qiskit counts, use --format qiskit_counts with a JSON object "
|
|
307
|
+
'like {"00": 10, "11": 6} or {"counts": {"00": 10, "11": 6}}.',
|
|
308
|
+
file=sys.stderr,
|
|
309
|
+
)
|
|
310
|
+
return 2
|
|
311
|
+
json_label = "<redacted-local-path>" if args.share_safe else args.out_json
|
|
312
|
+
md_label = "<redacted-local-path>" if args.share_safe else args.out_md
|
|
313
|
+
print(f"Wrote execution review JSON to {json_label}", file=sys.stderr)
|
|
314
|
+
print(f"Wrote execution review Markdown to {md_label}", file=sys.stderr)
|
|
315
|
+
return 0
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def _cmd_mcp(argv: list[str]) -> int:
|
|
319
|
+
p = argparse.ArgumentParser(
|
|
320
|
+
prog="qcoder mcp",
|
|
321
|
+
add_help=True,
|
|
322
|
+
description=(
|
|
323
|
+
"Local read-only qCoder MCP for Cursor. Uses explicit user-selected inputs only; "
|
|
324
|
+
"does not execute circuits, modify code, use tokens, or call live services."
|
|
325
|
+
),
|
|
259
326
|
)
|
|
260
|
-
|
|
261
|
-
|
|
327
|
+
sub = p.add_subparsers(dest="mcp_command")
|
|
328
|
+
p_serve = sub.add_parser("serve", help="Serve qCoder tools over MCP stdio.")
|
|
329
|
+
p_serve.set_defaults(mcp_command="serve")
|
|
330
|
+
args = p.parse_args(argv)
|
|
331
|
+
if args.mcp_command is None:
|
|
332
|
+
p.print_help()
|
|
333
|
+
return 0
|
|
334
|
+
if args.mcp_command == "serve":
|
|
335
|
+
from qcoder.mcp.server import serve_stdio
|
|
336
|
+
|
|
337
|
+
return serve_stdio()
|
|
338
|
+
p.print_help()
|
|
262
339
|
return 0
|
|
263
340
|
|
|
264
341
|
|
|
@@ -318,14 +395,20 @@ def _format_summary_value(value: str | int | float | bool) -> str:
|
|
|
318
395
|
return str(value)
|
|
319
396
|
|
|
320
397
|
|
|
321
|
-
def _print_raw_payload_json(payload: dict[str, object] | None) -> None:
|
|
322
|
-
|
|
398
|
+
def _print_raw_payload_json(payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
|
|
399
|
+
out = payload or {}
|
|
400
|
+
if share_safe:
|
|
401
|
+
out = make_share_safe_payload(out)
|
|
402
|
+
print(json.dumps(out, indent=2, sort_keys=True))
|
|
323
403
|
|
|
324
404
|
|
|
325
|
-
def _write_json_payload(path: str, payload: dict[str, object] | None) -> None:
|
|
405
|
+
def _write_json_payload(path: str, payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
|
|
406
|
+
out = payload or {}
|
|
407
|
+
if share_safe:
|
|
408
|
+
out = make_share_safe_payload(out)
|
|
326
409
|
out_path = Path(path)
|
|
327
410
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
328
|
-
out_path.write_text(json.dumps(
|
|
411
|
+
out_path.write_text(json.dumps(out, indent=2, sort_keys=True), encoding="utf-8")
|
|
329
412
|
|
|
330
413
|
|
|
331
414
|
def _is_scalar(value: object) -> bool:
|
|
@@ -468,6 +551,11 @@ def _render_student_evidence_markdown(payload: dict[str, object] | None) -> str:
|
|
|
468
551
|
"# qCoder Explorer Beta Guided Evidence",
|
|
469
552
|
"",
|
|
470
553
|
]
|
|
554
|
+
if payload and payload.get("share_safe") is True:
|
|
555
|
+
lines.append(render_share_safe_note().strip())
|
|
556
|
+
lines.append("")
|
|
557
|
+
lines.append(render_share_safe_provenance(payload).strip())
|
|
558
|
+
lines.append("")
|
|
471
559
|
for line in _summarize_student_evidence_payload(payload):
|
|
472
560
|
lines.append(f"- {line}")
|
|
473
561
|
if payload:
|
|
@@ -490,10 +578,13 @@ def _render_student_evidence_markdown(payload: dict[str, object] | None) -> str:
|
|
|
490
578
|
return "\n".join(lines)
|
|
491
579
|
|
|
492
580
|
|
|
493
|
-
def _write_markdown_payload(path: str, payload: dict[str, object] | None) -> None:
|
|
581
|
+
def _write_markdown_payload(path: str, payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
|
|
582
|
+
out = payload or {}
|
|
583
|
+
if share_safe:
|
|
584
|
+
out = make_share_safe_payload(out)
|
|
494
585
|
out_path = Path(path)
|
|
495
586
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
496
|
-
out_path.write_text(_render_student_evidence_markdown(
|
|
587
|
+
out_path.write_text(_render_student_evidence_markdown(out), encoding="utf-8")
|
|
497
588
|
|
|
498
589
|
|
|
499
590
|
def _run_student_builtin_review_check(
|
|
@@ -577,6 +668,7 @@ def _run_student_evidence_check(
|
|
|
577
668
|
context_json_path: str | None = None,
|
|
578
669
|
out_json: str | None = None,
|
|
579
670
|
out_md: str | None = None,
|
|
671
|
+
share_safe: bool = False,
|
|
580
672
|
) -> int:
|
|
581
673
|
request_payload: dict[str, object] | None = None
|
|
582
674
|
if qasm_path and context_json_path:
|
|
@@ -618,11 +710,11 @@ def _run_student_evidence_check(
|
|
|
618
710
|
return 2
|
|
619
711
|
|
|
620
712
|
if json_output:
|
|
621
|
-
_print_raw_payload_json(response.payload)
|
|
713
|
+
_print_raw_payload_json(response.payload, share_safe=share_safe)
|
|
622
714
|
if out_json:
|
|
623
|
-
_write_json_payload(out_json, response.payload)
|
|
715
|
+
_write_json_payload(out_json, response.payload, share_safe=share_safe)
|
|
624
716
|
if out_md:
|
|
625
|
-
_write_markdown_payload(out_md, response.payload)
|
|
717
|
+
_write_markdown_payload(out_md, response.payload, share_safe=share_safe)
|
|
626
718
|
return 0 if response.status_code == 200 else 1 if response.status_code in {401, 403} else 2
|
|
627
719
|
|
|
628
720
|
if response.status_code == 200:
|
|
@@ -637,11 +729,11 @@ def _run_student_evidence_check(
|
|
|
637
729
|
for line in _summarize_student_evidence_payload(response.payload):
|
|
638
730
|
print(f" {line}")
|
|
639
731
|
if out_json:
|
|
640
|
-
_write_json_payload(out_json, response.payload)
|
|
641
|
-
print(f" wrote_json: {out_json}")
|
|
732
|
+
_write_json_payload(out_json, response.payload, share_safe=share_safe)
|
|
733
|
+
print(f" wrote_json: {'<redacted-local-path>' if share_safe else out_json}")
|
|
642
734
|
if out_md:
|
|
643
|
-
_write_markdown_payload(out_md, response.payload)
|
|
644
|
-
print(f" wrote_md: {out_md}")
|
|
735
|
+
_write_markdown_payload(out_md, response.payload, share_safe=share_safe)
|
|
736
|
+
print(f" wrote_md: {'<redacted-local-path>' if share_safe else out_md}")
|
|
645
737
|
return 0
|
|
646
738
|
if response.status_code == 401:
|
|
647
739
|
print(
|
|
@@ -724,6 +816,13 @@ def _cmd_explorer(argv: list[str], *, compatibility_alias: bool = False) -> int:
|
|
|
724
816
|
)
|
|
725
817
|
p_evidence.add_argument("--out-json", default=None, help="Write Explorer evidence response JSON.")
|
|
726
818
|
p_evidence.add_argument("--out-md", default=None, help="Write Explorer evidence response Markdown.")
|
|
819
|
+
p_evidence.add_argument(
|
|
820
|
+
"--share-safe",
|
|
821
|
+
"--redact",
|
|
822
|
+
dest="share_safe",
|
|
823
|
+
action="store_true",
|
|
824
|
+
help="Write output artifacts with explicit share-safe metadata and local-sensitive details redacted.",
|
|
825
|
+
)
|
|
727
826
|
p_evidence.set_defaults(explorer_command="evidence")
|
|
728
827
|
|
|
729
828
|
args = p.parse_args(argv)
|
|
@@ -749,6 +848,7 @@ def _cmd_explorer(argv: list[str], *, compatibility_alias: bool = False) -> int:
|
|
|
749
848
|
context_json_path=args.context_json,
|
|
750
849
|
out_json=args.out_json,
|
|
751
850
|
out_md=args.out_md,
|
|
851
|
+
share_safe=args.share_safe,
|
|
752
852
|
)
|
|
753
853
|
|
|
754
854
|
p.print_help()
|
|
@@ -1140,14 +1240,15 @@ def _cmd_pro(argv: list[str]) -> int:
|
|
|
1140
1240
|
|
|
1141
1241
|
def _print_root_help() -> None:
|
|
1142
1242
|
print(
|
|
1143
|
-
"usage: qcoder [--version | -V] [-h] {analyze,batch,context,review,explorer,pro,student} ...\n\n"
|
|
1243
|
+
"usage: qcoder [--version | -V] [-h] {analyze,batch,context,review,mcp,explorer,pro,student} ...\n\n"
|
|
1144
1244
|
"Quantum circuit analysis CLI.\n\n"
|
|
1145
1245
|
"positional arguments:\n"
|
|
1146
|
-
" {analyze,batch,context,review,explorer,pro,student} subcommand\n\n"
|
|
1246
|
+
" {analyze,batch,context,review,mcp,explorer,pro,student} subcommand\n\n"
|
|
1147
1247
|
" analyze Analyze a QASM file (feature extraction + metadata + run config).\n"
|
|
1148
1248
|
" batch Batch extract a directory to JSONL (requires --out).\n"
|
|
1149
1249
|
" context Build deterministic preflight context artifacts.\n"
|
|
1150
1250
|
" review Build deterministic execution review artifacts from counts.\n"
|
|
1251
|
+
" mcp Serve local read-only qCoder tools for Cursor over MCP stdio.\n"
|
|
1151
1252
|
" explorer Explorer Beta status/demo/evidence checks.\n"
|
|
1152
1253
|
" pro Archived Pro client-contract shell (not current public product).\n"
|
|
1153
1254
|
" student Compatibility alias for Explorer Beta checks.\n\n"
|
|
@@ -1179,6 +1280,8 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1179
1280
|
return _cmd_context(rest)
|
|
1180
1281
|
if cmd == "review":
|
|
1181
1282
|
return _cmd_review(rest)
|
|
1283
|
+
if cmd == "mcp":
|
|
1284
|
+
return _cmd_mcp(rest)
|
|
1182
1285
|
if cmd == "explorer":
|
|
1183
1286
|
return _cmd_explorer(rest)
|
|
1184
1287
|
if cmd == "pro":
|
|
@@ -1187,7 +1290,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1187
1290
|
return _cmd_student(rest)
|
|
1188
1291
|
|
|
1189
1292
|
print(
|
|
1190
|
-
f"qcoder: unknown subcommand {cmd!r} (expected analyze, batch, context, review, explorer, pro, or student)",
|
|
1293
|
+
f"qcoder: unknown subcommand {cmd!r} (expected analyze, batch, context, review, mcp, explorer, pro, or student)",
|
|
1191
1294
|
file=sys.stderr,
|
|
1192
1295
|
)
|
|
1193
1296
|
print("Run `qcoder --help` for usage.", file=sys.stderr)
|
|
@@ -60,9 +60,15 @@ class RunConfig:
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
def to_dict(self) -> dict:
|
|
63
|
+
analysis_backend = "local_gpu" if self.backend == "GPU" else "local_cpu"
|
|
63
64
|
return {
|
|
64
65
|
"processor": self.processor,
|
|
65
66
|
"backend": self.backend,
|
|
67
|
+
"analysis_backend": analysis_backend,
|
|
68
|
+
"local_analysis_backend": analysis_backend,
|
|
69
|
+
"backend_meaning": (
|
|
70
|
+
"local analysis backend; not a simulator, QPU, or hardware execution backend"
|
|
71
|
+
),
|
|
66
72
|
"precision": self.precision,
|
|
67
73
|
"threshold": self.threshold,
|
|
68
74
|
}
|