@ictechgy/context-guard 0.4.4 → 0.4.5

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 (27) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.ko.md +15 -2
  3. package/README.md +12 -2
  4. package/context-guard-kit/README.md +2 -2
  5. package/context-guard-kit/benchmark_runner.py +244 -6
  6. package/context-guard-kit/claude_transcript_cost_audit.py +171 -1
  7. package/docs/benchmark-fixtures/learned-compression-baseline-context-pack.prompt.example.md +19 -0
  8. package/docs/benchmark-fixtures/learned-compression-candidate-digest.prompt.example.md +21 -0
  9. package/docs/benchmark-fixtures/learned-compression.tasks.example.json +5 -1
  10. package/docs/benchmark-fixtures/output-transform-baseline-raw-output.prompt.example.md +20 -0
  11. package/docs/benchmark-fixtures/output-transform-digest-receipt.prompt.example.md +23 -0
  12. package/docs/benchmark-fixtures/output-transform.tasks.example.json +28 -0
  13. package/docs/benchmark-fixtures/output-transform.variants.example.json +10 -0
  14. package/docs/benchmark-fixtures/visual-ocr-cropped-ocr.prompt.example.md +22 -0
  15. package/docs/benchmark-fixtures/visual-ocr-full-visual.prompt.example.md +19 -0
  16. package/docs/benchmark-fixtures/visual-ocr.tasks.example.json +5 -1
  17. package/docs/benchmark-workflow-examples.md +6 -2
  18. package/docs/benchmark-workflows/self-hosted-metrics-ledger.example.jsonl +1 -0
  19. package/docs/experimental-benchmark-fixtures.md +17 -6
  20. package/docs/mac-visibility-feasibility-schema.md +62 -0
  21. package/docs/mac-visibility-feasibility.example.json +130 -0
  22. package/package.json +5 -1
  23. package/plugins/context-guard/.claude-plugin/plugin.json +1 -1
  24. package/plugins/context-guard/README.ko.md +1 -1
  25. package/plugins/context-guard/README.md +1 -1
  26. package/plugins/context-guard/bin/context-guard-audit +171 -1
  27. package/plugins/context-guard/bin/context-guard-bench +244 -6
@@ -0,0 +1,130 @@
1
+ {
2
+ "schema_version": "contextguard.metric-feasibility.v1.3",
3
+ "producer": "context-guard-audit",
4
+ "generated_at": "2026-06-08T12:00:00Z",
5
+ "consumer_contract": {
6
+ "stable_top_level_fields": [
7
+ "schema_version",
8
+ "producer",
9
+ "generated_at",
10
+ "source_kind",
11
+ "source_freshness",
12
+ "scan_integrity",
13
+ "metric_availability",
14
+ "metric_caveats",
15
+ "redaction_mode",
16
+ "context_availability",
17
+ "headroom_availability",
18
+ "cache_friendliness",
19
+ "cache_diagnostics",
20
+ "cache_layout_advice",
21
+ "mac_visibility",
22
+ "totals"
23
+ ],
24
+ "diagnostic_fields": ["summary"],
25
+ "summary_contract": "summary is the legacy audit JSON payload for diagnostics and backward compatibility; new GUI prototypes should bind to stable top-level feasibility fields first."
26
+ },
27
+ "source_kind": "historical_transcript_scan",
28
+ "source_freshness": {
29
+ "status": "snapshot_at_scan_time",
30
+ "live": false,
31
+ "generated_at": "2026-06-08T12:00:00Z",
32
+ "description": "Local transcript files were scanned when this report was generated; this is not a live statusline snapshot."
33
+ },
34
+ "scan_integrity": {
35
+ "status": "complete",
36
+ "files_scanned": 1,
37
+ "records_scanned": 1,
38
+ "skipped_files": 0,
39
+ "skipped_records": 0,
40
+ "parse_error_count": 0,
41
+ "complete": true
42
+ },
43
+ "metric_availability": {
44
+ "tokens": {"status": "available", "present_fields": {"input": 1, "output": 1, "cache_read": 1, "cache_creation": 1}, "evidence": "observed"},
45
+ "cache": {"status": "available", "present_fields": {"cache_read": 1, "cache_creation": 1}, "zero_values_observed": {"cache_read": false, "cache_creation": false}, "evidence": "observed"},
46
+ "cost": {"status": "available", "present_count": 1, "observed_cost_usd": 0.1234, "evidence": "observed"},
47
+ "context": {"status": "missing", "evidence": "unavailable", "reason": "Transcript scans do not include live Claude Code context_window data. Pass a live statusline snapshot in a future surface to populate context availability."},
48
+ "headroom": {"status": "missing", "evidence": "unavailable", "reason": "Transcript scans do not carry live context-window or remaining-token data, so context headroom cannot be observed or conservatively inferred from history alone.", "observable_via": "live_statusline_snapshot"}
49
+ },
50
+ "metric_caveats": [
51
+ "Values are observed from local Claude Code transcript JSON/JSONL fields and are not official billing records.",
52
+ "cache-read share is cache_read / (input + cache_read + cache_creation), not a provider billing hit-rate."
53
+ ],
54
+ "redaction_mode": {
55
+ "paths": "basename_plus_stable_hash_by_default",
56
+ "commands": "command_category_plus_stable_hash_by_default",
57
+ "secret_like_values": "pattern_redacted",
58
+ "raw_path_and_command_flags": ["--show-paths", "--show-commands"]
59
+ },
60
+ "context_availability": {"status": "missing", "evidence": "unavailable", "reason": "Transcript scans do not include live Claude Code context_window data. Pass a live statusline snapshot in a future surface to populate context availability."},
61
+ "headroom_availability": {"status": "missing", "evidence": "unavailable", "observable_via": "live_statusline_snapshot", "reason": "Transcript scans do not carry live context-window or remaining-token data, so context headroom cannot be observed or conservatively inferred from history alone."},
62
+ "cache_friendliness": {"status": "partial", "confidence": "partial", "evidence": "observed", "heuristic": true},
63
+ "cache_diagnostics": {
64
+ "schema_version": "contextguard.cache-diagnostics.v1",
65
+ "status": "partial",
66
+ "confidence": "hypothesis",
67
+ "evidence": "inferred",
68
+ "heuristic": true,
69
+ "dynamic_prefix_breakers": [],
70
+ "headroom_diagnostics": {"status": "missing", "evidence": "unavailable", "observable_via": "live_statusline_snapshot", "required_observation": "live_statusline_snapshot", "historical_total_tokens_are_not_headroom": true}
71
+ },
72
+ "cache_layout_advice": {
73
+ "schema_version": "contextguard.cache-layout-advice.v1",
74
+ "status": "partial",
75
+ "confidence": "partial",
76
+ "priority": "P1",
77
+ "observed_issue": "long_session_accumulation"
78
+ },
79
+ "mac_visibility": {
80
+ "schema_version": "contextguard.mac-visibility.v1",
81
+ "surface_kind": "local_macos_visibility_contract",
82
+ "readiness": {
83
+ "status": "ready",
84
+ "reason": "Transcript token totals are available and the scan completed within configured limits."
85
+ },
86
+ "bind_to_top_level_fields": [
87
+ "source_kind",
88
+ "source_freshness",
89
+ "scan_integrity",
90
+ "metric_availability",
91
+ "metric_caveats",
92
+ "redaction_mode",
93
+ "context_availability",
94
+ "headroom_availability",
95
+ "cache_friendliness",
96
+ "cache_diagnostics",
97
+ "cache_layout_advice",
98
+ "totals"
99
+ ],
100
+ "diagnostic_only_fields": ["summary"],
101
+ "primary_cards": [
102
+ {"id": "source_freshness", "title": "Source freshness", "status": "available", "binding_paths": ["source_kind", "source_freshness.status", "source_freshness.generated_at"]},
103
+ {"id": "scan_integrity", "title": "Scan integrity", "status": "complete", "binding_paths": ["scan_integrity.status", "scan_integrity.files_scanned", "scan_integrity.records_scanned", "scan_integrity.skipped_files", "scan_integrity.skipped_records"]},
104
+ {"id": "token_totals", "title": "Token totals", "status": "available", "binding_paths": ["totals.total_tokens", "totals.tokens.input", "totals.tokens.output", "totals.tokens.cache_read", "totals.tokens.cache_creation"]},
105
+ {"id": "cache_reuse", "title": "Cache-read share and reuse ratio", "status": "available", "binding_paths": ["totals.cache_read_share", "totals.cache_reuse_ratio", "metric_availability.cache"]},
106
+ {"id": "observed_cost", "title": "Observed transcript cost", "status": "available", "binding_paths": ["totals.cost_usd_observed", "metric_availability.cost"]},
107
+ {"id": "context_availability", "title": "Context availability", "status": "missing", "binding_paths": ["context_availability", "metric_availability.context"], "required_observation": "live_statusline_snapshot"},
108
+ {"id": "headroom_availability", "title": "Headroom availability", "status": "missing", "binding_paths": ["headroom_availability", "cache_diagnostics.headroom_diagnostics"], "required_observation": "live_statusline_snapshot"},
109
+ {"id": "cache_layout_advice", "title": "Cache layout advice", "status": "partial", "binding_paths": ["cache_layout_advice", "cache_friendliness", "cache_diagnostics.dynamic_prefix_breakers"]}
110
+ ],
111
+ "missing_live_observations": [
112
+ {"id": "live_context_window", "required_observation": "live_statusline_snapshot", "affects": ["context_availability", "metric_availability.context"], "reason": "Historical transcript scans do not include live Claude Code context_window data."},
113
+ {"id": "live_headroom", "required_observation": "live_statusline_snapshot", "affects": ["headroom_availability", "cache_diagnostics.headroom_diagnostics"], "reason": "Historical transcript totals are not remaining-token or live headroom observations."}
114
+ ],
115
+ "claim_boundaries": [
116
+ "Local transcript observations are not invoice-grade billing records.",
117
+ "Provider cache fields are telemetry, not ContextGuard-caused token reduction and do not prove provider cache hits.",
118
+ "Historical transcript totals do not infer live context headroom or remaining tokens.",
119
+ "This contract does not guarantee token or cost savings."
120
+ ],
121
+ "redaction_required": true
122
+ },
123
+ "totals": {
124
+ "total_tokens": 1150,
125
+ "tokens": {"input": 100, "output": 50, "cache_read": 800, "cache_creation": 200},
126
+ "cost_usd_observed": 0.1234,
127
+ "cache_read_share": 0.7272727272727273,
128
+ "cache_reuse_ratio": 4.0
129
+ }
130
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ictechgy/context-guard",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "ContextGuard CLI helpers for keeping AI coding agent context focused and local-first.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/ictechgy/context-guard#readme",
@@ -55,9 +55,13 @@
55
55
  "docs/cache-diagnostics-schema.md",
56
56
  "docs/cache-diagnostics.schema.json",
57
57
  "docs/cache-diagnostics.example.json",
58
+ "docs/mac-visibility-feasibility-schema.md",
59
+ "docs/mac-visibility-feasibility.example.json",
58
60
  "docs/benchmark-workflows/*.example.json",
61
+ "docs/benchmark-workflows/*.example.jsonl",
59
62
  "docs/benchmark-workflow-examples.md",
60
63
  "docs/benchmark-fixtures/*.example.json",
64
+ "docs/benchmark-fixtures/*.prompt.example.md",
61
65
  "docs/experimental-benchmark-fixtures.md",
62
66
  "packaging/homebrew/context-guard.rb.template"
63
67
  ],
@@ -37,5 +37,5 @@
37
37
  "gated-experiments",
38
38
  "future-roadmap"
39
39
  ],
40
- "version": "0.4.4"
40
+ "version": "0.4.5"
41
41
  }
@@ -97,7 +97,7 @@ context-guard-statusline-merged
97
97
  - **상태표시줄**은 모델, 컨텍스트, 비용 신호를 짧게 보여주고, 대화 기록 데이터가 있으면 캐시 읽기와 캐시 재사용 신호도 함께 표시합니다.
98
98
  - **대화 기록 감사**는 usage/cost/cache bucket을 집계하고, 토큰 집중 지점, `cache_friendliness` 프롬프트 배치 신호, `cache_layout_advice` 확인/실험 우선순위를 제한된 가림 처리된 segment hash로 보고합니다. 원문 프롬프트는 출력하지 않습니다.
99
99
  - **반복 실패 알림**은 Bash 실패가 반복될 때 같은 경로를 계속 재시도하지 않고 전략을 바꾸도록 안내합니다.
100
- - **벤치마크 헬퍼**는 기준/변형 실행을 대응해 실제 토큰·비용 필드, 별도의 바이트 감소 간접 증거, 진단용 `wall_time_seconds`, `provider_cached_tokens`, provider-cache 사용 가능성 텔레메트리로 기록합니다.
100
+ - **벤치마크 헬퍼**는 기준/변형 실행을 대응해 실제 토큰·비용 필드, 별도의 바이트 감소 간접 증거, 진단용 `wall_time_seconds`, `provider_cached_tokens`, provider-cache 사용 가능성 텔레메트리, 파일 기반 `variant_prompt_files`, 선택적 run별 `self_hosted_metrics` JSONL ledger sidecar를 기록합니다. 이 sidecar는 hosted API 절감 주장에 합치지 않습니다.
101
101
 
102
102
  비용 가드의 로컬 HMAC 키는 기본적으로 `.context-guard/cost-ledger/hmac.key`에 자동 생성됩니다. 관리자가 직접 주입하는 경우 파일에는 필수 padding을 포함한 canonical URL-safe base64 32바이트 키만 정확히 들어 있어야 하며, trailing newline이나 공백은 허용하지 않습니다. 리포트는 키와 원문 프롬프트를 출력하지 않고, 로컬 ledger는 Anthropic/provider prompt cache를 대체하지 않습니다.
103
103
 
@@ -103,7 +103,7 @@ context-guard-statusline-merged
103
103
  - **Statusline** displays compact model/context/cost signals and, when transcript data is available, cache-read and cache-reuse signals.
104
104
  - **Transcript audit** aggregates usage/cost/cache buckets, flags likely token hotspots, and exposes `cache_friendliness`, additive [`cache_diagnostics`](https://github.com/ictechgy/context-guard/blob/main/docs/cache-diagnostics-schema.md), and `cache_layout_advice` experiment priorities from bounded usage fields, timestamped cache telemetry records, and redacted segment hashes without printing raw prompt text or claiming provider-cache savings.
105
105
  - **Repeated-failure nudge** warns after repeated Bash failures so the agent switches strategy instead of retrying the same context-heavy path.
106
- - **Benchmark helper** records matched baseline/variant runs with real token and cost fields, separate byte-reduction proxy evidence, diagnostic `wall_time_seconds`, `provider_cached_tokens`, and provider-cache availability telemetry.
106
+ - **Benchmark helper** records matched baseline/variant runs with real token and cost fields, separate byte-reduction proxy evidence, diagnostic `wall_time_seconds`, `provider_cached_tokens`, provider-cache availability telemetry, file-backed `variant_prompt_files`, and optional per-run `self_hosted_metrics` JSONL ledger sidecars that stay out of hosted API savings claims.
107
107
 
108
108
  Cost guard creates its local HMAC key automatically at `.context-guard/cost-ledger/hmac.key`. If you provision that file yourself, it must contain exactly one canonical URL-safe base64 32-byte key with required padding and no trailing newline or whitespace. Reports never emit the key or raw prompt text, and the local ledger does not replace Anthropic/provider prompt caching.
109
109
 
@@ -46,7 +46,8 @@ COST_KEYS = ("total_cost_usd", "cost_usd", "costUSD")
46
46
  MODEL_KEYS = ("model", "model_id", "modelId")
47
47
  QUERY_SOURCE_KEYS = ("query_source", "querySource")
48
48
  TIMESTAMP_KEYS = ("timestamp", "created_at", "createdAt", "time", "ts")
49
- FEASIBILITY_SCHEMA_VERSION = "contextguard.metric-feasibility.v1.2"
49
+ FEASIBILITY_SCHEMA_VERSION = "contextguard.metric-feasibility.v1.3"
50
+ MAC_VISIBILITY_SCHEMA_VERSION = "contextguard.mac-visibility.v1"
50
51
  FEASIBILITY_PRODUCER = "context-guard-audit"
51
52
  CACHE_DIAGNOSTICS_SCHEMA_VERSION = "contextguard.cache-diagnostics.v1"
52
53
  CACHE_LAYOUT_ADVICE_SCHEMA_VERSION = "contextguard.cache-layout-advice.v1"
@@ -1635,6 +1636,168 @@ def build_metric_caveats(summary: UsageSummary) -> list[str]:
1635
1636
  return caveats
1636
1637
 
1637
1638
 
1639
+ def _mac_card(
1640
+ card_id: str,
1641
+ title: str,
1642
+ status: str,
1643
+ binding_paths: list[str],
1644
+ *,
1645
+ required_observation: str | None = None,
1646
+ ) -> dict[str, Any]:
1647
+ card: dict[str, Any] = {
1648
+ "id": card_id,
1649
+ "title": title,
1650
+ "status": status,
1651
+ "binding_paths": binding_paths,
1652
+ }
1653
+ if required_observation:
1654
+ card["required_observation"] = required_observation
1655
+ return card
1656
+
1657
+
1658
+ def build_mac_visibility_contract(
1659
+ *,
1660
+ availability: dict[str, Any],
1661
+ integrity: dict[str, Any],
1662
+ cache_layout_advice: dict[str, Any],
1663
+ ) -> dict[str, Any]:
1664
+ """Build the pre-GUI macOS visibility binding contract.
1665
+
1666
+ This is intentionally a thin index over already-emitted stable feasibility
1667
+ fields. It does not recompute metrics, read diagnostic summary data, or infer
1668
+ live context/headroom from historical transcript totals.
1669
+ """
1670
+ token_status = str((availability.get("tokens") or {}).get("status", "missing"))
1671
+ scan_status = str(integrity.get("status", "partial"))
1672
+ if token_status == "available" and scan_status == "complete":
1673
+ readiness_status = "ready"
1674
+ readiness_reason = "Transcript token totals are available and the scan completed within configured limits."
1675
+ elif token_status in {"available", "partial"}:
1676
+ readiness_status = "partial"
1677
+ readiness_reason = "Some stable fields can be shown, but scan integrity or metric availability is partial."
1678
+ else:
1679
+ readiness_status = "missing"
1680
+ readiness_reason = "Token totals are missing from the transcript scan; show setup or unavailable state."
1681
+
1682
+ context_status = str((availability.get("context") or {}).get("status", "missing"))
1683
+ headroom_status = str((availability.get("headroom") or {}).get("status", "missing"))
1684
+ cache_status = str((availability.get("cache") or {}).get("status", "missing"))
1685
+ cost_status = str((availability.get("cost") or {}).get("status", "missing"))
1686
+ advice_status = str(cache_layout_advice.get("status", "missing"))
1687
+
1688
+ missing_live_observations: list[dict[str, Any]] = []
1689
+ if context_status == "missing":
1690
+ missing_live_observations.append({
1691
+ "id": "live_context_window",
1692
+ "required_observation": "live_statusline_snapshot",
1693
+ "affects": ["context_availability", "metric_availability.context"],
1694
+ "reason": "Historical transcript scans do not include live Claude Code context_window data.",
1695
+ })
1696
+ if headroom_status == "missing":
1697
+ missing_live_observations.append({
1698
+ "id": "live_headroom",
1699
+ "required_observation": "live_statusline_snapshot",
1700
+ "affects": ["headroom_availability", "cache_diagnostics.headroom_diagnostics"],
1701
+ "reason": "Historical transcript totals are not remaining-token or live headroom observations.",
1702
+ })
1703
+
1704
+ return {
1705
+ "schema_version": MAC_VISIBILITY_SCHEMA_VERSION,
1706
+ "surface_kind": "local_macos_visibility_contract",
1707
+ "readiness": {
1708
+ "status": readiness_status,
1709
+ "reason": readiness_reason,
1710
+ },
1711
+ "bind_to_top_level_fields": [
1712
+ "source_kind",
1713
+ "source_freshness",
1714
+ "scan_integrity",
1715
+ "metric_availability",
1716
+ "metric_caveats",
1717
+ "redaction_mode",
1718
+ "context_availability",
1719
+ "headroom_availability",
1720
+ "cache_friendliness",
1721
+ "cache_diagnostics",
1722
+ "cache_layout_advice",
1723
+ "totals",
1724
+ ],
1725
+ "diagnostic_only_fields": ["summary"],
1726
+ "primary_cards": [
1727
+ _mac_card(
1728
+ "source_freshness",
1729
+ "Source freshness",
1730
+ "available",
1731
+ ["source_kind", "source_freshness.status", "source_freshness.generated_at"],
1732
+ ),
1733
+ _mac_card(
1734
+ "scan_integrity",
1735
+ "Scan integrity",
1736
+ scan_status,
1737
+ [
1738
+ "scan_integrity.status",
1739
+ "scan_integrity.files_scanned",
1740
+ "scan_integrity.records_scanned",
1741
+ "scan_integrity.skipped_files",
1742
+ "scan_integrity.skipped_records",
1743
+ ],
1744
+ ),
1745
+ _mac_card(
1746
+ "token_totals",
1747
+ "Token totals",
1748
+ token_status,
1749
+ [
1750
+ "totals.total_tokens",
1751
+ "totals.tokens.input",
1752
+ "totals.tokens.output",
1753
+ "totals.tokens.cache_read",
1754
+ "totals.tokens.cache_creation",
1755
+ ],
1756
+ ),
1757
+ _mac_card(
1758
+ "cache_reuse",
1759
+ "Cache-read share and reuse ratio",
1760
+ cache_status,
1761
+ ["totals.cache_read_share", "totals.cache_reuse_ratio", "metric_availability.cache"],
1762
+ ),
1763
+ _mac_card(
1764
+ "observed_cost",
1765
+ "Observed transcript cost",
1766
+ cost_status,
1767
+ ["totals.cost_usd_observed", "metric_availability.cost"],
1768
+ ),
1769
+ _mac_card(
1770
+ "context_availability",
1771
+ "Context availability",
1772
+ context_status,
1773
+ ["context_availability", "metric_availability.context"],
1774
+ required_observation="live_statusline_snapshot" if context_status == "missing" else None,
1775
+ ),
1776
+ _mac_card(
1777
+ "headroom_availability",
1778
+ "Headroom availability",
1779
+ headroom_status,
1780
+ ["headroom_availability", "cache_diagnostics.headroom_diagnostics"],
1781
+ required_observation="live_statusline_snapshot" if headroom_status == "missing" else None,
1782
+ ),
1783
+ _mac_card(
1784
+ "cache_layout_advice",
1785
+ "Cache layout advice",
1786
+ advice_status,
1787
+ ["cache_layout_advice", "cache_friendliness", "cache_diagnostics.dynamic_prefix_breakers"],
1788
+ ),
1789
+ ],
1790
+ "missing_live_observations": missing_live_observations,
1791
+ "claim_boundaries": [
1792
+ "Local transcript observations are not invoice-grade billing records.",
1793
+ "Provider cache fields are telemetry, not ContextGuard-caused token reduction and do not prove provider cache hits.",
1794
+ "Historical transcript totals do not infer live context headroom or remaining tokens.",
1795
+ "This contract does not guarantee token or cost savings.",
1796
+ ],
1797
+ "redaction_required": True,
1798
+ }
1799
+
1800
+
1638
1801
  def feasibility_json(
1639
1802
  summary: UsageSummary,
1640
1803
  top: int = 15,
@@ -1652,6 +1815,11 @@ def feasibility_json(
1652
1815
  cache_friendliness = cache_friendliness_for_summary(summary)
1653
1816
  cache_diagnostics = cache_diagnostics_for_summary(summary)
1654
1817
  cache_layout_advice = cache_layout_advice_for_summary(summary)
1818
+ mac_visibility = build_mac_visibility_contract(
1819
+ availability=availability,
1820
+ integrity=integrity,
1821
+ cache_layout_advice=cache_layout_advice,
1822
+ )
1655
1823
  return {
1656
1824
  "schema_version": FEASIBILITY_SCHEMA_VERSION,
1657
1825
  "producer": FEASIBILITY_PRODUCER,
@@ -1672,6 +1840,7 @@ def feasibility_json(
1672
1840
  "cache_friendliness",
1673
1841
  "cache_diagnostics",
1674
1842
  "cache_layout_advice",
1843
+ "mac_visibility",
1675
1844
  "totals",
1676
1845
  ],
1677
1846
  "diagnostic_fields": ["summary"],
@@ -1701,6 +1870,7 @@ def feasibility_json(
1701
1870
  "cache_friendliness": cache_friendliness,
1702
1871
  "cache_diagnostics": cache_diagnostics,
1703
1872
  "cache_layout_advice": cache_layout_advice,
1873
+ "mac_visibility": mac_visibility,
1704
1874
  "totals": {
1705
1875
  "total_tokens": stable_total_tokens,
1706
1876
  "tokens": stable_tokens,