qcoder 0.5.0a5__tar.gz → 0.5.0a6__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 (72) hide show
  1. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/CHANGELOG.md +12 -0
  2. {qcoder-0.5.0a5/src/qcoder.egg-info → qcoder-0.5.0a6}/PKG-INFO +12 -1
  3. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/README.md +11 -0
  4. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/pyproject.toml +1 -1
  5. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/__init__.py +1 -1
  6. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/cli.py +79 -19
  7. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/run_config.py +6 -0
  8. qcoder-0.5.0a6/src/qcoder/core/share_safe.py +278 -0
  9. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/context/bundle.py +2 -1
  10. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/context/markdown.py +7 -1
  11. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/review/bundle.py +4 -1
  12. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/review/markdown.py +7 -1
  13. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pipelines/analyze.py +11 -0
  14. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pipelines/context.py +4 -1
  15. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pipelines/review.py +13 -1
  16. {qcoder-0.5.0a5 → qcoder-0.5.0a6/src/qcoder.egg-info}/PKG-INFO +12 -1
  17. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder.egg-info/SOURCES.txt +1 -0
  18. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/LICENSE +0 -0
  19. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/MANIFEST.in +0 -0
  20. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/NOTICE +0 -0
  21. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/setup.cfg +0 -0
  22. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/__main__.py +0 -0
  23. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/__init__.py +0 -0
  24. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/context.py +0 -0
  25. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/qasm2/__init__.py +0 -0
  26. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/qasm2/adjoint_eligibility.py +0 -0
  27. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/qasm2/mirror_build.py +0 -0
  28. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/core/schema.py +0 -0
  29. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/context/__init__.py +0 -0
  30. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/adapters/__init__.py +0 -0
  31. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/adapters/cirq_intake.py +0 -0
  32. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/adapters/pennylane_intake.py +0 -0
  33. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/adapters/qiskit_intake.py +0 -0
  34. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/extractor.py +0 -0
  35. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/features/compute_v0.py +0 -0
  36. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/features/glossary_v0.py +0 -0
  37. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/features/schema_v0.py +0 -0
  38. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/ir.py +0 -0
  39. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/labeling.py +0 -0
  40. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/parsers/__init__.py +0 -0
  41. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/qasm2_regex_parser.py +0 -0
  42. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/cut_profile.py +0 -0
  43. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/depth.py +0 -0
  44. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/entangling_layers.py +0 -0
  45. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/gate_set_stats.py +0 -0
  46. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/interaction_graph.py +0 -0
  47. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/interaction_graph_metrics.py +0 -0
  48. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/feature_extraction/reps/spans.py +0 -0
  49. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/guidance/__init__.py +0 -0
  50. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/guidance/model_pack.py +0 -0
  51. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/guidance/resource.py +0 -0
  52. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/guidance/structural_scores.py +0 -0
  53. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/profiles/__init__.py +0 -0
  54. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/profiles/feature_profiles_v0.py +0 -0
  55. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/review/__init__.py +0 -0
  56. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/review/counts_v0.py +0 -0
  57. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/engines/review/qiskit_counts.py +0 -0
  58. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/explorer/__init__.py +0 -0
  59. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/explorer/derived_evidence.py +0 -0
  60. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/model_packs/__init__.py +0 -0
  61. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/model_packs/resource_guidance_local_v0.json +0 -0
  62. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pipelines/batch.py +0 -0
  63. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pro_preview/__init__.py +0 -0
  64. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pro_preview/client.py +0 -0
  65. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pro_preview/config.py +0 -0
  66. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pro_preview/errors.py +0 -0
  67. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/pro_preview/manifest.py +0 -0
  68. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder/tools/batch.py +0 -0
  69. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder.egg-info/dependency_links.txt +0 -0
  70. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder.egg-info/entry_points.txt +0 -0
  71. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder.egg-info/requires.txt +0 -0
  72. {qcoder-0.5.0a5 → qcoder-0.5.0a6}/src/qcoder.egg-info/top_level.txt +0 -0
@@ -1,6 +1,18 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## 0.5.0a6
5
+
6
+ - Add share-safe / redacted artifact mode for artifacts intended for ChatGPT, Cursor, email, GitHub issues, or support threads.
7
+ - Add `--share-safe` / `--redact` to OSS artifact commands and Explorer evidence file output.
8
+ - Emit share-safety metadata in JSON artifacts: `share_safe`, `redactions_applied`, `raw_qasm_included`, `local_paths_included`, and `tokens_included`.
9
+ - Add a visible share-safe note to Markdown artifacts.
10
+ - 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.
11
+ - Preserve normal rich local artifacts by default; share-safe mode is opt-in.
12
+ - Share-safe mode is designed for safer sharing and users should still review artifacts before sharing. It is not a privacy guarantee.
13
+ - Remaining P1 hardening: forward-slash UNC variants, broader Linux root patterns, independent post-scan hardening, and expanded docs wording.
14
+
15
+
4
16
  ## 0.5.0a5
5
17
 
6
18
  - 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.0a5
3
+ Version: 0.5.0a6
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>
@@ -77,6 +77,16 @@ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md p
77
77
  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
78
  ```
79
79
 
80
+ For artifacts you intend to paste into ChatGPT, Cursor, email, GitHub issues, or support threads, add `--share-safe`:
81
+
82
+ ```bash
83
+ qcoder analyze path/to/circuit.qasm --json --share-safe
84
+ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md preflight.context.md --share-safe
85
+ 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
86
+ ```
87
+
88
+ 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.
89
+
80
90
  Explorer Beta compatibility checks and archived Pro bootstrap:
81
91
 
82
92
  ```bash
@@ -85,6 +95,7 @@ qcoder explorer demo
85
95
  qcoder explorer evidence
86
96
  qcoder explorer evidence --qasm path/to/circuit.qasm
87
97
  qcoder explorer evidence --context-json preflight.context.json
98
+ qcoder explorer evidence --qasm path/to/circuit.qasm --out-json explorer.json --out-md explorer.md --share-safe
88
99
  qcoder pro --help
89
100
  ```
90
101
 
@@ -47,6 +47,16 @@ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md p
47
47
  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
48
  ```
49
49
 
50
+ For artifacts you intend to paste into ChatGPT, Cursor, email, GitHub issues, or support threads, add `--share-safe`:
51
+
52
+ ```bash
53
+ qcoder analyze path/to/circuit.qasm --json --share-safe
54
+ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md preflight.context.md --share-safe
55
+ 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
56
+ ```
57
+
58
+ 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.
59
+
50
60
  Explorer Beta compatibility checks and archived Pro bootstrap:
51
61
 
52
62
  ```bash
@@ -55,6 +65,7 @@ qcoder explorer demo
55
65
  qcoder explorer evidence
56
66
  qcoder explorer evidence --qasm path/to/circuit.qasm
57
67
  qcoder explorer evidence --context-json preflight.context.json
68
+ qcoder explorer evidence --qasm path/to/circuit.qasm --out-json explorer.json --out-md explorer.md --share-safe
58
69
  qcoder pro --help
59
70
  ```
60
71
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qcoder"
7
- version = "0.5.0a5"
7
+ version = "0.5.0a6"
8
8
  description = "Quantum circuit analysis and structured feature extraction tools."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,3 +1,3 @@
1
1
  __all__ = []
2
- __version__ = "0.5.0a5"
2
+ __version__ = "0.5.0a6"
3
3
  file = __file__
@@ -8,6 +8,11 @@ from pathlib import Path
8
8
  from qcoder.pipelines.analyze import analyze_qasm
9
9
  from qcoder.pipelines.context import write_preflight_context
10
10
  from qcoder.pipelines.review import write_execution_review
11
+ from qcoder.core.share_safe import (
12
+ make_share_safe_payload,
13
+ render_share_safe_note,
14
+ render_share_safe_provenance,
15
+ )
11
16
  from qcoder.explorer.derived_evidence import (
12
17
  ExplorerDerivedEvidenceRequestError,
13
18
  build_derived_evidence_request_from_context_json,
@@ -100,6 +105,13 @@ def _cmd_analyze(argv: list[str]) -> int:
100
105
  help="Include derived feature_profiles in JSON output (requires --json for analyze)",
101
106
  )
102
107
  p.add_argument("--json", action="store_true", help="Emit machine-readable JSON")
108
+ p.add_argument(
109
+ "--share-safe",
110
+ "--redact",
111
+ dest="share_safe",
112
+ action="store_true",
113
+ help="Redact local paths and sensitive runtime details in JSON output intended for sharing.",
114
+ )
103
115
  args = p.parse_args(argv)
104
116
 
105
117
  if args.profiles and not args.json:
@@ -120,9 +132,12 @@ def _cmd_analyze(argv: list[str]) -> int:
120
132
  )
121
133
 
122
134
  if args.json:
135
+ payload = report.to_json_dict(include_guidance=args.guidance, include_profiles=args.profiles)
136
+ if args.share_safe:
137
+ payload = make_share_safe_payload(payload)
123
138
  print(
124
139
  json.dumps(
125
- report.to_json_dict(include_guidance=args.guidance, include_profiles=args.profiles),
140
+ payload,
126
141
  indent=2,
127
142
  sort_keys=True,
128
143
  )
@@ -131,7 +146,9 @@ def _cmd_analyze(argv: list[str]) -> int:
131
146
 
132
147
  ex = report.example
133
148
  rc = report.run_config
134
- print(f"file: {ex.qasm_path}")
149
+ print(f"file: {'<redacted-local-path>' if args.share_safe else ex.qasm_path}")
150
+ if args.share_safe:
151
+ print("share_safe: true")
135
152
  print(f"format: {ex.ir.source_format}")
136
153
  if ex.name:
137
154
  print(f"name: {ex.name}")
@@ -218,6 +235,13 @@ def _cmd_context(argv: list[str]) -> int:
218
235
  action="store_true",
219
236
  help="Include full feature glossary/appendix in context artifacts (default: selected structural features only)",
220
237
  )
238
+ p.add_argument(
239
+ "--share-safe",
240
+ "--redact",
241
+ dest="share_safe",
242
+ action="store_true",
243
+ help="Write artifacts designed for safer sharing by redacting local paths and sensitive runtime details.",
244
+ )
221
245
  args = p.parse_args(argv)
222
246
 
223
247
  write_preflight_context(
@@ -229,9 +253,12 @@ def _cmd_context(argv: list[str]) -> int:
229
253
  include_full_features=args.full_features,
230
254
  circuit_id=args.circuit_id,
231
255
  circuit_name=args.circuit_name,
256
+ share_safe=args.share_safe,
232
257
  )
233
- print(f"Wrote preflight context JSON to {args.out_json}", file=sys.stderr)
234
- print(f"Wrote preflight context Markdown to {args.out_md}", file=sys.stderr)
258
+ json_label = "<redacted-local-path>" if args.share_safe else args.out_json
259
+ md_label = "<redacted-local-path>" if args.share_safe else args.out_md
260
+ print(f"Wrote preflight context JSON to {json_label}", file=sys.stderr)
261
+ print(f"Wrote preflight context Markdown to {md_label}", file=sys.stderr)
235
262
  return 0
236
263
 
237
264
 
@@ -248,6 +275,13 @@ def _cmd_review(argv: list[str]) -> int:
248
275
  p.add_argument("--preflight-json", default=None, help="Optional preflight context JSON path for linkage/checks")
249
276
  p.add_argument("--out-json", required=True, help="Output execution review JSON path")
250
277
  p.add_argument("--out-md", required=True, help="Output execution review Markdown path")
278
+ p.add_argument(
279
+ "--share-safe",
280
+ "--redact",
281
+ dest="share_safe",
282
+ action="store_true",
283
+ help="Write artifacts designed for safer sharing by redacting local paths and sensitive runtime details.",
284
+ )
251
285
  args = p.parse_args(argv)
252
286
 
253
287
  write_execution_review(
@@ -256,9 +290,12 @@ def _cmd_review(argv: list[str]) -> int:
256
290
  preflight_json=args.preflight_json,
257
291
  out_json=args.out_json,
258
292
  out_md=args.out_md,
293
+ share_safe=args.share_safe,
259
294
  )
260
- print(f"Wrote execution review JSON to {args.out_json}", file=sys.stderr)
261
- print(f"Wrote execution review Markdown to {args.out_md}", file=sys.stderr)
295
+ json_label = "<redacted-local-path>" if args.share_safe else args.out_json
296
+ md_label = "<redacted-local-path>" if args.share_safe else args.out_md
297
+ print(f"Wrote execution review JSON to {json_label}", file=sys.stderr)
298
+ print(f"Wrote execution review Markdown to {md_label}", file=sys.stderr)
262
299
  return 0
263
300
 
264
301
 
@@ -318,14 +355,20 @@ def _format_summary_value(value: str | int | float | bool) -> str:
318
355
  return str(value)
319
356
 
320
357
 
321
- def _print_raw_payload_json(payload: dict[str, object] | None) -> None:
322
- print(json.dumps(payload or {}, indent=2, sort_keys=True))
358
+ def _print_raw_payload_json(payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
359
+ out = payload or {}
360
+ if share_safe:
361
+ out = make_share_safe_payload(out)
362
+ print(json.dumps(out, indent=2, sort_keys=True))
323
363
 
324
364
 
325
- def _write_json_payload(path: str, payload: dict[str, object] | None) -> None:
365
+ def _write_json_payload(path: str, payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
366
+ out = payload or {}
367
+ if share_safe:
368
+ out = make_share_safe_payload(out)
326
369
  out_path = Path(path)
327
370
  out_path.parent.mkdir(parents=True, exist_ok=True)
328
- out_path.write_text(json.dumps(payload or {}, indent=2, sort_keys=True), encoding="utf-8")
371
+ out_path.write_text(json.dumps(out, indent=2, sort_keys=True), encoding="utf-8")
329
372
 
330
373
 
331
374
  def _is_scalar(value: object) -> bool:
@@ -468,6 +511,11 @@ def _render_student_evidence_markdown(payload: dict[str, object] | None) -> str:
468
511
  "# qCoder Explorer Beta Guided Evidence",
469
512
  "",
470
513
  ]
514
+ if payload and payload.get("share_safe") is True:
515
+ lines.append(render_share_safe_note().strip())
516
+ lines.append("")
517
+ lines.append(render_share_safe_provenance(payload).strip())
518
+ lines.append("")
471
519
  for line in _summarize_student_evidence_payload(payload):
472
520
  lines.append(f"- {line}")
473
521
  if payload:
@@ -490,10 +538,13 @@ def _render_student_evidence_markdown(payload: dict[str, object] | None) -> str:
490
538
  return "\n".join(lines)
491
539
 
492
540
 
493
- def _write_markdown_payload(path: str, payload: dict[str, object] | None) -> None:
541
+ def _write_markdown_payload(path: str, payload: dict[str, object] | None, *, share_safe: bool = False) -> None:
542
+ out = payload or {}
543
+ if share_safe:
544
+ out = make_share_safe_payload(out)
494
545
  out_path = Path(path)
495
546
  out_path.parent.mkdir(parents=True, exist_ok=True)
496
- out_path.write_text(_render_student_evidence_markdown(payload), encoding="utf-8")
547
+ out_path.write_text(_render_student_evidence_markdown(out), encoding="utf-8")
497
548
 
498
549
 
499
550
  def _run_student_builtin_review_check(
@@ -577,6 +628,7 @@ def _run_student_evidence_check(
577
628
  context_json_path: str | None = None,
578
629
  out_json: str | None = None,
579
630
  out_md: str | None = None,
631
+ share_safe: bool = False,
580
632
  ) -> int:
581
633
  request_payload: dict[str, object] | None = None
582
634
  if qasm_path and context_json_path:
@@ -618,11 +670,11 @@ def _run_student_evidence_check(
618
670
  return 2
619
671
 
620
672
  if json_output:
621
- _print_raw_payload_json(response.payload)
673
+ _print_raw_payload_json(response.payload, share_safe=share_safe)
622
674
  if out_json:
623
- _write_json_payload(out_json, response.payload)
675
+ _write_json_payload(out_json, response.payload, share_safe=share_safe)
624
676
  if out_md:
625
- _write_markdown_payload(out_md, response.payload)
677
+ _write_markdown_payload(out_md, response.payload, share_safe=share_safe)
626
678
  return 0 if response.status_code == 200 else 1 if response.status_code in {401, 403} else 2
627
679
 
628
680
  if response.status_code == 200:
@@ -637,11 +689,11 @@ def _run_student_evidence_check(
637
689
  for line in _summarize_student_evidence_payload(response.payload):
638
690
  print(f" {line}")
639
691
  if out_json:
640
- _write_json_payload(out_json, response.payload)
641
- print(f" wrote_json: {out_json}")
692
+ _write_json_payload(out_json, response.payload, share_safe=share_safe)
693
+ print(f" wrote_json: {'<redacted-local-path>' if share_safe else out_json}")
642
694
  if out_md:
643
- _write_markdown_payload(out_md, response.payload)
644
- print(f" wrote_md: {out_md}")
695
+ _write_markdown_payload(out_md, response.payload, share_safe=share_safe)
696
+ print(f" wrote_md: {'<redacted-local-path>' if share_safe else out_md}")
645
697
  return 0
646
698
  if response.status_code == 401:
647
699
  print(
@@ -724,6 +776,13 @@ def _cmd_explorer(argv: list[str], *, compatibility_alias: bool = False) -> int:
724
776
  )
725
777
  p_evidence.add_argument("--out-json", default=None, help="Write Explorer evidence response JSON.")
726
778
  p_evidence.add_argument("--out-md", default=None, help="Write Explorer evidence response Markdown.")
779
+ p_evidence.add_argument(
780
+ "--share-safe",
781
+ "--redact",
782
+ dest="share_safe",
783
+ action="store_true",
784
+ help="Write output artifacts with explicit share-safe metadata and local-sensitive details redacted.",
785
+ )
727
786
  p_evidence.set_defaults(explorer_command="evidence")
728
787
 
729
788
  args = p.parse_args(argv)
@@ -749,6 +808,7 @@ def _cmd_explorer(argv: list[str], *, compatibility_alias: bool = False) -> int:
749
808
  context_json_path=args.context_json,
750
809
  out_json=args.out_json,
751
810
  out_md=args.out_md,
811
+ share_safe=args.share_safe,
752
812
  )
753
813
 
754
814
  p.print_help()
@@ -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
  }
@@ -0,0 +1,278 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import re
5
+ from pathlib import PurePath
6
+ from typing import Any
7
+
8
+
9
+ SHARE_SAFE_NOTE = (
10
+ "Share-safe means local paths, raw circuit text, and token-like values are "
11
+ "omitted or redacted where detected. It is designed for safer sharing, not "
12
+ "a privacy guarantee, and it does not hide circuit structure."
13
+ )
14
+ SCHEMA_VERSION_NOTE = (
15
+ "qCoder package versions and artifact/schema versions are versioned separately."
16
+ )
17
+ SUPPORTED_CLAIMS = (
18
+ "deterministic structural features",
19
+ "pre-execution circuit shape",
20
+ "local artifact review context",
21
+ )
22
+ UNSUPPORTED_CLAIMS = (
23
+ "runtime prediction",
24
+ "fidelity or backend ranking",
25
+ "correctness proof",
26
+ "quantum advantage",
27
+ "raw hosted QASM",
28
+ )
29
+
30
+ _REDACTED_LOCAL_PATH = "<redacted-local-path>"
31
+ _REDACTED_SENSITIVE_VALUE = "<redacted-sensitive-value>"
32
+
33
+ _PATH_TERMINATOR_CHARS = r"\s`'\"<>|"
34
+ _LOCAL_PATH_RE = re.compile(
35
+ r"(?P<path>"
36
+ r"(?:[A-Za-z]:[\\/][^" + _PATH_TERMINATOR_CHARS + r"]+)"
37
+ r"|(?:\\\\[^\\/" + _PATH_TERMINATOR_CHARS + r"]+[\\/][^" + _PATH_TERMINATOR_CHARS + r"]+)"
38
+ r"|(?:~[\\/][^" + _PATH_TERMINATOR_CHARS + r"]+)"
39
+ r"|(?:/(?:home|Users|mnt|private|var|tmp|workspace|workspaces)/[^" + _PATH_TERMINATOR_CHARS + r"]+)"
40
+ r")"
41
+ )
42
+ _TOKEN_LIKE_RE = re.compile(
43
+ r"(?i)(bearer\s+)[A-Za-z0-9._~+/=-]{8,}|"
44
+ r"(authorization\s*[:=]\s*)(?:bearer\s+)?[^\n,;]+|"
45
+ r"(cookie\s*[:=]\s*)[^\n,;]+|"
46
+ r"(session\s*[:=]\s*)[^\n,;]+|"
47
+ r"(identity[-_ ]?token\s*[:=]\s*)[^\n,;]+|"
48
+ r"(QCODER_[A-Z_]*TOKEN\s*=\s*)[^\s]+|"
49
+ r"(pypi-)[A-Za-z0-9._-]{8,}"
50
+ )
51
+ _FORBIDDEN_TEXT_MARKERS = (
52
+ "OPENQASM 2.0",
53
+ "OPENQASM 3.0",
54
+ "qreg ",
55
+ "creg ",
56
+ "Secret Manager",
57
+ "Postmark",
58
+ )
59
+ _PATH_KEYS = {
60
+ "qasm_path",
61
+ "preflight_context_path",
62
+ "counts_json",
63
+ "source_path",
64
+ "local_path",
65
+ "path",
66
+ }
67
+ _RAW_KEYS = {
68
+ "raw_qasm",
69
+ "qasm_text",
70
+ "source_text",
71
+ "raw_source_text",
72
+ "prompt",
73
+ "notebook",
74
+ "auth_header",
75
+ "authorization",
76
+ "cookie",
77
+ "session",
78
+ "token",
79
+ }
80
+
81
+
82
+ def make_share_safe_payload(payload: dict[str, Any]) -> dict[str, Any]:
83
+ redactions: set[str] = set()
84
+ sanitized = _sanitize(copy.deepcopy(payload), redactions=redactions, key_path=())
85
+ if not isinstance(sanitized, dict):
86
+ sanitized = {"value": sanitized}
87
+ _add_artifact_identity(sanitized)
88
+ _clarify_run_config(sanitized)
89
+ sanitized["share_safe"] = True
90
+ sanitized["redactions_applied"] = sorted(redactions)
91
+ serialized = _stable_string(sanitized)
92
+ sanitized["raw_qasm_included"] = contains_raw_qasm_marker(serialized)
93
+ sanitized["local_paths_included"] = contains_local_path(serialized)
94
+ token_like_secrets_included = contains_token_or_header(serialized)
95
+ sanitized["token_like_secrets_included"] = token_like_secrets_included
96
+ sanitized["tokens_included"] = token_like_secrets_included
97
+ sanitized["tokens_included_meaning"] = (
98
+ "authentication tokens or token-like secrets, not LLM token counts"
99
+ )
100
+ sanitized["share_safe_note"] = SHARE_SAFE_NOTE
101
+ sanitized["schema_version_note"] = SCHEMA_VERSION_NOTE
102
+ sanitized["supported_claims"] = list(SUPPORTED_CLAIMS)
103
+ sanitized["unsupported_claims"] = list(UNSUPPORTED_CLAIMS)
104
+ return sanitized
105
+
106
+
107
+ def render_share_safe_note() -> str:
108
+ return f"> **{SHARE_SAFE_NOTE}**\n\n"
109
+
110
+
111
+ def render_share_safe_provenance(payload: dict[str, Any]) -> str:
112
+ """Render compact share-safe provenance for Markdown artifacts."""
113
+ lines = ["## Share-safe provenance", ""]
114
+ for label, value in _provenance_items(payload):
115
+ lines.append(f"- {label}: `{value}`")
116
+ redactions = payload.get("redactions_applied")
117
+ if isinstance(redactions, list):
118
+ redaction_text = ", ".join(str(item) for item in redactions) if redactions else "none"
119
+ lines.append(f"- redactions_applied: `{redaction_text}`")
120
+ lines.append("")
121
+ lines.append(SCHEMA_VERSION_NOTE)
122
+ lines.append("")
123
+ lines.append("## Supported by this artifact")
124
+ for item in SUPPORTED_CLAIMS:
125
+ lines.append(f"- {item}")
126
+ lines.append("")
127
+ lines.append("## Not supported by this artifact")
128
+ for item in UNSUPPORTED_CLAIMS:
129
+ lines.append(f"- {item}")
130
+ lines.append("")
131
+ return "\n".join(lines)
132
+
133
+
134
+ def _provenance_items(payload: dict[str, Any]) -> list[tuple[str, Any]]:
135
+ schema = (
136
+ payload.get("schema_id")
137
+ or payload.get("context_bundle_schema_version")
138
+ or payload.get("review_bundle_schema_version")
139
+ or payload.get("artifact_type")
140
+ or "unknown"
141
+ )
142
+ fingerprint = None
143
+ hashes = payload.get("hashes")
144
+ if isinstance(hashes, dict):
145
+ fingerprint = hashes.get("qasm_sha256") or hashes.get("analysis_fingerprint")
146
+ if fingerprint is None:
147
+ linkage = payload.get("linkage")
148
+ if isinstance(linkage, dict):
149
+ fingerprint = linkage.get("qasm_sha256") or linkage.get("analysis_fingerprint")
150
+ return [
151
+ ("qcoder_version", payload.get("qcoder_version", "unknown")),
152
+ ("artifact_schema", schema),
153
+ ("qcoder_product_path", payload.get("qcoder_product_path", "unknown")),
154
+ ("artifact_role", payload.get("artifact_role", "unknown")),
155
+ ("share_safe", payload.get("share_safe", "unknown")),
156
+ ("raw_qasm_included", payload.get("raw_qasm_included", "unknown")),
157
+ ("local_paths_included", payload.get("local_paths_included", "unknown")),
158
+ (
159
+ "token_like_secrets_included",
160
+ payload.get("token_like_secrets_included", payload.get("tokens_included", "unknown")),
161
+ ),
162
+ ("qasm_sha256_or_analysis_fingerprint", fingerprint or "not_available"),
163
+ ]
164
+
165
+
166
+ def _add_artifact_identity(payload: dict[str, Any]) -> None:
167
+ if payload.get("qcoder_product_path") and payload.get("artifact_role"):
168
+ return
169
+ schema_id = str(payload.get("schema_id") or "")
170
+ mode = str(payload.get("mode") or "")
171
+ artifact_type = str(payload.get("artifact_type") or "")
172
+ if schema_id.startswith("qcoder.explorer.") or mode == "explorer-custom-guided-evidence":
173
+ payload.setdefault("qcoder_product_path", "explorer_beta")
174
+ payload.setdefault("artifact_role", "derived_context_guided_evidence")
175
+ elif payload.get("context_bundle_schema_version") or artifact_type == "qcoder.preflight_context":
176
+ payload.setdefault("qcoder_product_path", "oss")
177
+ payload.setdefault("artifact_role", "local_preflight_context")
178
+ elif payload.get("review_bundle_schema_version") or artifact_type == "qcoder.execution_review":
179
+ payload.setdefault("qcoder_product_path", "oss")
180
+ payload.setdefault("artifact_role", "local_execution_review")
181
+ elif "feature_map" in payload and "features" in payload:
182
+ payload.setdefault("qcoder_product_path", "oss")
183
+ payload.setdefault("artifact_role", "local_analysis_report")
184
+
185
+
186
+ def _clarify_run_config(payload: dict[str, Any]) -> None:
187
+ run_config = payload.get("run_config")
188
+ if not isinstance(run_config, dict):
189
+ return
190
+ backend = str(run_config.get("backend") or "").strip().lower()
191
+ if backend == "gpu":
192
+ local_backend = "local_gpu"
193
+ else:
194
+ local_backend = "local_cpu"
195
+ run_config.setdefault("analysis_backend", local_backend)
196
+ run_config.setdefault("local_analysis_backend", local_backend)
197
+ run_config.setdefault(
198
+ "backend_meaning",
199
+ "local analysis backend; not a simulator, QPU, or hardware execution backend",
200
+ )
201
+
202
+
203
+ def _sanitize(value: Any, *, redactions: set[str], key_path: tuple[str, ...]) -> Any:
204
+ key = key_path[-1] if key_path else ""
205
+ key_lower = key.lower()
206
+ if isinstance(value, dict):
207
+ out: dict[str, Any] = {}
208
+ for child_key, child_value in value.items():
209
+ child_key_str = str(child_key)
210
+ if child_key_str.lower() in _RAW_KEYS:
211
+ out[child_key_str] = _REDACTED_SENSITIVE_VALUE
212
+ redactions.add(f"field:{child_key_str}")
213
+ continue
214
+ out[child_key_str] = _sanitize(
215
+ child_value,
216
+ redactions=redactions,
217
+ key_path=key_path + (child_key_str,),
218
+ )
219
+ return out
220
+ if isinstance(value, list):
221
+ return [_sanitize(item, redactions=redactions, key_path=key_path) for item in value]
222
+ if isinstance(value, tuple):
223
+ return [_sanitize(item, redactions=redactions, key_path=key_path) for item in value]
224
+ if isinstance(value, str):
225
+ if key_lower in _PATH_KEYS:
226
+ redactions.add(f"field:{key}")
227
+ return _REDACTED_LOCAL_PATH
228
+ return _sanitize_text(value, redactions=redactions)
229
+ return value
230
+
231
+
232
+ def _sanitize_text(text: str, *, redactions: set[str]) -> str:
233
+ out = text
234
+ for marker in _FORBIDDEN_TEXT_MARKERS:
235
+ if marker in out:
236
+ out = out.replace(marker, _REDACTED_SENSITIVE_VALUE)
237
+ redactions.add("raw_or_sensitive_text")
238
+
239
+ def _path_repl(match: re.Match[str]) -> str:
240
+ redactions.add("absolute_path")
241
+ return _REDACTED_LOCAL_PATH
242
+
243
+ out = _LOCAL_PATH_RE.sub(_path_repl, out)
244
+
245
+ def _token_repl(match: re.Match[str]) -> str:
246
+ redactions.add("token_or_header_like_text")
247
+ return _REDACTED_SENSITIVE_VALUE
248
+
249
+ out = _TOKEN_LIKE_RE.sub(_token_repl, out)
250
+ return out
251
+
252
+
253
+ def _stable_string(value: Any) -> str:
254
+ try:
255
+ import json
256
+
257
+ return json.dumps(value, sort_keys=True, ensure_ascii=False)
258
+ except Exception:
259
+ return str(value)
260
+
261
+
262
+ def contains_local_path(text: str) -> bool:
263
+ return bool(_LOCAL_PATH_RE.search(text))
264
+
265
+
266
+ def contains_token_or_header(text: str) -> bool:
267
+ return bool(_TOKEN_LIKE_RE.search(text))
268
+
269
+
270
+ def contains_raw_qasm_marker(text: str) -> bool:
271
+ return any(marker in text for marker in ("OPENQASM 2.0", "OPENQASM 3.0", "qreg ", "creg "))
272
+
273
+
274
+ def is_probable_absolute_path(value: str) -> bool:
275
+ try:
276
+ return PurePath(value).is_absolute() or contains_local_path(value)
277
+ except Exception:
278
+ return False
@@ -88,6 +88,8 @@ def build_context_bundle(
88
88
  return {
89
89
  "context_bundle_schema_version": "0.1",
90
90
  "artifact_type": "qcoder.preflight_context",
91
+ "qcoder_product_path": "oss",
92
+ "artifact_role": "local_preflight_context",
91
93
  "basis": context_bundle_basis(analysis),
92
94
  "generated_utc": generated_utc or utc_now_iso(),
93
95
  "qcoder_version": qcoder_version,
@@ -106,4 +108,3 @@ def build_context_bundle(
106
108
  "limits": llm_limits,
107
109
  },
108
110
  }
109
-
@@ -2,6 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Any
4
4
 
5
+ from qcoder.core.share_safe import render_share_safe_note, render_share_safe_provenance
6
+
5
7
 
6
8
  def _fmt_num(value: Any) -> str:
7
9
  if isinstance(value, float) and value.is_integer():
@@ -24,6 +26,11 @@ def render_context_markdown(bundle: dict[str, Any]) -> str:
24
26
 
25
27
  lines.append("# qCoder Preflight Context")
26
28
  lines.append("")
29
+ if bundle.get("share_safe") is True:
30
+ lines.append(render_share_safe_note().strip())
31
+ lines.append("")
32
+ lines.append(render_share_safe_provenance(bundle).strip())
33
+ lines.append("")
27
34
  lines.append("## Purpose")
28
35
  lines.append("Deterministic pre-execution context artifact for planning and review.")
29
36
  lines.append("")
@@ -121,4 +128,3 @@ def render_context_markdown(bundle: dict[str, Any]) -> str:
121
128
  lines.append(bundle.get("llm_use", {}).get("intended_use", ""))
122
129
  lines.append("")
123
130
  return "\n".join(lines)
124
-
@@ -50,6 +50,7 @@ def build_review_bundle(
50
50
  counts_v0: dict[str, Any],
51
51
  preflight_context: dict[str, Any] | None = None,
52
52
  preflight_context_path: str | None = None,
53
+ qcoder_version: str | None = None,
53
54
  generated_utc: str | None = None,
54
55
  ) -> dict[str, Any]:
55
56
  counts = counts_v0.get("counts", {})
@@ -193,6 +194,9 @@ def build_review_bundle(
193
194
  return {
194
195
  "review_bundle_schema_version": "0.1",
195
196
  "artifact_type": "qcoder.execution_review",
197
+ "qcoder_product_path": "oss",
198
+ "artifact_role": "local_execution_review",
199
+ "qcoder_version": qcoder_version,
196
200
  "basis": "deterministic_counts_review",
197
201
  "generated_utc": generated_utc or utc_now_iso(),
198
202
  "inputs": {
@@ -228,4 +232,3 @@ def build_review_bundle(
228
232
  ],
229
233
  },
230
234
  }
231
-
@@ -2,6 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Any
4
4
 
5
+ from qcoder.core.share_safe import render_share_safe_note, render_share_safe_provenance
6
+
5
7
 
6
8
  def render_review_markdown(bundle: dict[str, Any]) -> str:
7
9
  lines: list[str] = []
@@ -14,6 +16,11 @@ def render_review_markdown(bundle: dict[str, Any]) -> str:
14
16
 
15
17
  lines.append("# qCoder Execution Review")
16
18
  lines.append("")
19
+ if bundle.get("share_safe") is True:
20
+ lines.append(render_share_safe_note().strip())
21
+ lines.append("")
22
+ lines.append(render_share_safe_provenance(bundle).strip())
23
+ lines.append("")
17
24
  lines.append("## Purpose")
18
25
  lines.append("Deterministic post-execution review artifact from provided counts.")
19
26
  lines.append("Counts are user-provided; qCoder did not execute the circuit.")
@@ -107,4 +114,3 @@ def render_review_markdown(bundle: dict[str, Any]) -> str:
107
114
  lines.append(bundle.get("llm_use", {}).get("intended_use", ""))
108
115
  lines.append("")
109
116
  return "\n".join(lines)
110
-
@@ -2,12 +2,20 @@ from __future__ import annotations
2
2
 
3
3
  import hashlib
4
4
  from dataclasses import dataclass
5
+ from importlib.metadata import PackageNotFoundError, version
5
6
  from pathlib import Path
6
7
 
7
8
  from qcoder.core.run_config import RunConfig
8
9
  from qcoder.engines.feature_extraction.extractor import CircuitExample, extract_example
9
10
 
10
11
 
12
+ def _qcoder_version() -> str:
13
+ try:
14
+ return version("qcoder")
15
+ except PackageNotFoundError:
16
+ return "0+unknown"
17
+
18
+
11
19
  @dataclass(frozen=True)
12
20
  class AnalyzeReport:
13
21
  example: CircuitExample
@@ -19,6 +27,9 @@ class AnalyzeReport:
19
27
  fv = ex.global_features
20
28
  feature_map = dict(zip(fv.feature_names, fv.features))
21
29
  out = {
30
+ "qcoder_product_path": "oss",
31
+ "artifact_role": "local_analysis_report",
32
+ "qcoder_version": _qcoder_version(),
22
33
  "circuit_id": ex.id,
23
34
  "circuit_name": ex.name,
24
35
  "function_hint": ex.function_hint,
@@ -8,6 +8,7 @@ from typing import Any
8
8
  from qcoder.engines.context.bundle import build_context_bundle
9
9
  from qcoder.engines.context.markdown import render_context_markdown
10
10
  from qcoder.pipelines.analyze import analyze_qasm
11
+ from qcoder.core.share_safe import make_share_safe_payload
11
12
 
12
13
 
13
14
  def _qcoder_version() -> str:
@@ -49,6 +50,7 @@ def write_preflight_context(
49
50
  include_full_features: bool = False,
50
51
  circuit_id: str | None = None,
51
52
  circuit_name: str | None = None,
53
+ share_safe: bool = False,
52
54
  ) -> dict[str, Any]:
53
55
  bundle = build_preflight_context(
54
56
  qasm_path,
@@ -58,6 +60,8 @@ def write_preflight_context(
58
60
  circuit_id=circuit_id,
59
61
  circuit_name=circuit_name,
60
62
  )
63
+ if share_safe:
64
+ bundle = make_share_safe_payload(bundle)
61
65
  out_json_path = Path(out_json)
62
66
  out_md_path = Path(out_md)
63
67
  out_json_path.parent.mkdir(parents=True, exist_ok=True)
@@ -65,4 +69,3 @@ def write_preflight_context(
65
69
  out_json_path.write_text(json.dumps(bundle, indent=2, sort_keys=True), encoding="utf-8")
66
70
  out_md_path.write_text(render_context_markdown(bundle), encoding="utf-8")
67
71
  return bundle
68
-
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ from importlib.metadata import PackageNotFoundError, version
4
5
  from pathlib import Path
5
6
  from typing import Any
6
7
 
@@ -8,6 +9,14 @@ from qcoder.engines.review.bundle import build_review_bundle
8
9
  from qcoder.engines.review.counts_v0 import normalize_counts_v0
9
10
  from qcoder.engines.review.markdown import render_review_markdown
10
11
  from qcoder.engines.review.qiskit_counts import normalize_qiskit_counts_payload
12
+ from qcoder.core.share_safe import make_share_safe_payload
13
+
14
+
15
+ def _qcoder_version() -> str:
16
+ try:
17
+ return version("qcoder")
18
+ except PackageNotFoundError:
19
+ return "0+unknown"
11
20
 
12
21
 
13
22
  def _load_json(path: str) -> dict[str, Any]:
@@ -37,6 +46,7 @@ def build_execution_review(
37
46
  counts_v0=counts_v0,
38
47
  preflight_context=preflight,
39
48
  preflight_context_path=preflight_json,
49
+ qcoder_version=_qcoder_version(),
40
50
  )
41
51
 
42
52
 
@@ -47,12 +57,15 @@ def write_execution_review(
47
57
  out_json: str,
48
58
  out_md: str,
49
59
  preflight_json: str | None = None,
60
+ share_safe: bool = False,
50
61
  ) -> dict[str, Any]:
51
62
  bundle = build_execution_review(
52
63
  counts_json=counts_json,
53
64
  counts_format=counts_format,
54
65
  preflight_json=preflight_json,
55
66
  )
67
+ if share_safe:
68
+ bundle = make_share_safe_payload(bundle)
56
69
  out_json_path = Path(out_json)
57
70
  out_md_path = Path(out_md)
58
71
  out_json_path.parent.mkdir(parents=True, exist_ok=True)
@@ -60,4 +73,3 @@ def write_execution_review(
60
73
  out_json_path.write_text(json.dumps(bundle, indent=2, sort_keys=True), encoding="utf-8")
61
74
  out_md_path.write_text(render_review_markdown(bundle), encoding="utf-8")
62
75
  return bundle
63
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qcoder
3
- Version: 0.5.0a5
3
+ Version: 0.5.0a6
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>
@@ -77,6 +77,16 @@ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md p
77
77
  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
78
  ```
79
79
 
80
+ For artifacts you intend to paste into ChatGPT, Cursor, email, GitHub issues, or support threads, add `--share-safe`:
81
+
82
+ ```bash
83
+ qcoder analyze path/to/circuit.qasm --json --share-safe
84
+ qcoder context path/to/circuit.qasm --out-json preflight.context.json --out-md preflight.context.md --share-safe
85
+ 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
86
+ ```
87
+
88
+ 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.
89
+
80
90
  Explorer Beta compatibility checks and archived Pro bootstrap:
81
91
 
82
92
  ```bash
@@ -85,6 +95,7 @@ qcoder explorer demo
85
95
  qcoder explorer evidence
86
96
  qcoder explorer evidence --qasm path/to/circuit.qasm
87
97
  qcoder explorer evidence --context-json preflight.context.json
98
+ qcoder explorer evidence --qasm path/to/circuit.qasm --out-json explorer.json --out-md explorer.md --share-safe
88
99
  qcoder pro --help
89
100
  ```
90
101
 
@@ -17,6 +17,7 @@ src/qcoder/core/__init__.py
17
17
  src/qcoder/core/context.py
18
18
  src/qcoder/core/run_config.py
19
19
  src/qcoder/core/schema.py
20
+ src/qcoder/core/share_safe.py
20
21
  src/qcoder/core/qasm2/__init__.py
21
22
  src/qcoder/core/qasm2/adjoint_eligibility.py
22
23
  src/qcoder/core/qasm2/mirror_build.py
File without changes
File without changes
File without changes
File without changes