engineering-platform 2.2.0__tar.gz → 2.3.1__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.
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/PKG-INFO +1 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/pyproject.toml +1 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +10 -3
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/agent_state.py +79 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/dashboard.css +19 -7
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/dashboard.js +246 -19
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/dashboard_locales.mjs +90 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/capability_preflight.py +10 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/capability_review.py +37 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/central_data_transfer.py +117 -22
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/central_database.py +23 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/component_logging.py +30 -4
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/console_route_ownership.py +1 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/dependabot_producer.py +2 -2
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_executor.py +44 -4
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_host.py +364 -107
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_lifecycle.py +8 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_models.py +1 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_repository.py +91 -2
- engineering_platform-2.3.1/src/engineering_platform/installation_relocation.py +212 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/lifecycle_worker.py +5 -2
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/managed_autonomy.py +3 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/parity_context.py +4 -2
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/parity_lifecycle_dispatcher.py +58 -16
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/platform_bootstrap.py +16 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/platform_version.py +1 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_readiness.py +15 -4
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_recovery.py +25 -9
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/providers.py +2 -2
- engineering_platform-2.3.1/src/engineering_platform/qualification_runtime.py +189 -0
- engineering_platform-2.3.1/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +34 -0
- engineering_platform-2.3.1/src/engineering_platform/schemas/producer-readback-v1.schema.json +1 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/server.py +399 -33
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/server_service.py +39 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/storage.py +2 -1
- engineering_platform-2.3.1/src/engineering_platform/submission_service.py +805 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/templates/workspace-config.json +18 -4
- engineering_platform-2.3.1/src/engineering_platform/version_preparation_delivery.py +437 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform.egg-info/PKG-INFO +1 -1
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform.egg-info/SOURCES.txt +4 -0
- engineering_platform-2.2.0/src/engineering_platform/installation_relocation.py +0 -122
- engineering_platform-2.2.0/src/engineering_platform/submission_service.py +0 -317
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/README.md +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/setup.cfg +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/__init__.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/__main__.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/agent_trust.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/central_store_migration.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/codex_capacity.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/codex_chat.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/codex_observability.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/component_lock.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/console_presentation.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/contracts/__init__.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/contracts/ep_consumer.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/contracts/models.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/contracts/projection.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/dashboard_browser_validation.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/dashboard_state.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/dashboard_supervisor.swift +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/dashboard_translation.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/drift_diagnostics.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/emergency_recovery.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/engineering_memory.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/ep_consumer_credentials.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/evidence_projection.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_activity.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_context.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_errors.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_evidence.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_finalization.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_lease.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_readiness.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_reporting.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_timeout_policy.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_timing.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/execution_transaction.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/external_producer_binding.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/file_inbox.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/forensic_attribution.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/forensic_attribution_v2.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/forensic_delta.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/golden_scenario.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/host_admin.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/host_preflight.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/investigation_ledger.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/legacy_inbox_migration.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/live_status.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/local_api.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/local_api_keychain.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/local_repository_binding.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/managed_codex_runtime.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/platform_admin.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/platform_api.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/platform_components.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/pr_check_repair.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/pr_evidence_backfill.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/producer.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/project_agent.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/project_agent_service.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/project_topology.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/prompt_history.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_context.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_context_benchmark.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_context_scope.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_interruption.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_process_identity.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/provider_usage.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/qualification.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/recommendation_handoff.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/report_analysis.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/repository_attachment.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/repository_handoff.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/resources.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/reviewer_evidence.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/server_console_services.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/server_relay.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/status_model.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/status_reconciliation.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/submission_cli.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/submission_intake.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/telemetry.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/validation_identity.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/validation_profile.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/workspace_preflight.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/worktree_provenance.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/worktree_tooling.py +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform.egg-info/entry_points.txt +0 -0
- {engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform.egg-info/top_level.txt +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"platform": {
|
|
4
4
|
"id": "engineering-platform",
|
|
5
5
|
"name": "Engineering Platform",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.3.1",
|
|
7
7
|
"generation": 2,
|
|
8
8
|
"documentation_namespace": "engineering-platform",
|
|
9
9
|
"capability_registry_version": 1
|
|
@@ -11,8 +11,15 @@
|
|
|
11
11
|
"workspace": {
|
|
12
12
|
"id": "engineering-platform",
|
|
13
13
|
"name": "Engineering Platform",
|
|
14
|
-
"repository": {
|
|
15
|
-
|
|
14
|
+
"repository": {
|
|
15
|
+
"provider": "github",
|
|
16
|
+
"owner": "pcvantol",
|
|
17
|
+
"name": "engineering-platform",
|
|
18
|
+
"default_branch": "main"
|
|
19
|
+
},
|
|
20
|
+
"branding": {
|
|
21
|
+
"dashboard_title": "EP Operations"
|
|
22
|
+
},
|
|
16
23
|
"workspace_authorization": {
|
|
17
24
|
"allowed_roots": [],
|
|
18
25
|
"allowed_repositories": [],
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bootstrap_contract": "2026.12",
|
|
3
3
|
"checkpoint_format": 1,
|
|
4
|
-
"dashboard_version": "2.
|
|
4
|
+
"dashboard_version": "2.3.1",
|
|
5
5
|
"handoff_protocol": 1,
|
|
6
6
|
"memory_format": 2,
|
|
7
7
|
"minimum_codex_cli": "0.146.0",
|
|
8
8
|
"inbox_protocol": 1,
|
|
9
|
-
"platform_version": "2.
|
|
9
|
+
"platform_version": "2.3.1",
|
|
10
10
|
"report_format": 2,
|
|
11
|
-
"runner_version": "2.
|
|
11
|
+
"runner_version": "2.3.1",
|
|
12
12
|
"status_model": 1,
|
|
13
13
|
"storage_schema": 41,
|
|
14
|
-
"watcher_version": "2.
|
|
14
|
+
"watcher_version": "2.3.1"
|
|
15
15
|
}
|
{engineering_platform-2.2.0 → engineering_platform-2.3.1}/src/engineering_platform/agent_state.py
RENAMED
|
@@ -135,6 +135,12 @@ class TransactionState:
|
|
|
135
135
|
agent_execution_seconds: float | None = None
|
|
136
136
|
validation_evidence: tuple[dict[str, str], ...] = ()
|
|
137
137
|
quality_evidence: tuple[dict[str, str], ...] = ()
|
|
138
|
+
# Versioned post-implementation assurance. These records are immutable
|
|
139
|
+
# observations; a later review appends a new record instead of changing an
|
|
140
|
+
# earlier finding into a pass.
|
|
141
|
+
assurance_profile: dict[str, str] | None = None
|
|
142
|
+
assurance_reviews: tuple[dict[str, object], ...] = ()
|
|
143
|
+
assurance_resolutions: tuple[dict[str, str], ...] = ()
|
|
138
144
|
repair_iterations: int = 0
|
|
139
145
|
repair_audit: tuple[dict[str, str], ...] = ()
|
|
140
146
|
local_validation_iterations: int = 0
|
|
@@ -172,6 +178,9 @@ class TransactionState:
|
|
|
172
178
|
"agent_execution_seconds": None,
|
|
173
179
|
"validation_evidence": (),
|
|
174
180
|
"quality_evidence": (),
|
|
181
|
+
"assurance_profile": None,
|
|
182
|
+
"assurance_reviews": (),
|
|
183
|
+
"assurance_resolutions": (),
|
|
175
184
|
"repair_iterations": 0,
|
|
176
185
|
"repair_audit": (),
|
|
177
186
|
"local_validation_iterations": 0,
|
|
@@ -194,6 +203,10 @@ class TransactionState:
|
|
|
194
203
|
raw = {**raw, "validation_evidence": tuple(raw["validation_evidence"])}
|
|
195
204
|
if isinstance(raw.get("quality_evidence"), list):
|
|
196
205
|
raw = {**raw, "quality_evidence": tuple(raw["quality_evidence"])}
|
|
206
|
+
if isinstance(raw.get("assurance_reviews"), list):
|
|
207
|
+
raw = {**raw, "assurance_reviews": tuple(raw["assurance_reviews"])}
|
|
208
|
+
if isinstance(raw.get("assurance_resolutions"), list):
|
|
209
|
+
raw = {**raw, "assurance_resolutions": tuple(raw["assurance_resolutions"])}
|
|
197
210
|
if isinstance(raw.get("repair_audit"), list):
|
|
198
211
|
raw = {**raw, "repair_audit": tuple(raw["repair_audit"])}
|
|
199
212
|
if isinstance(raw.get("local_validation_audit"), list):
|
|
@@ -274,17 +287,24 @@ class TransactionState:
|
|
|
274
287
|
)
|
|
275
288
|
):
|
|
276
289
|
raise StateError("checkpoint local validation audit is invalid or unsafe")
|
|
290
|
+
repair_audit_fields = audit_fields | {"repair_id", "origin", "input_candidate_sha", "dispatch_id"}
|
|
277
291
|
if (
|
|
278
292
|
not isinstance(state.repair_audit, tuple)
|
|
279
293
|
or len(state.repair_audit) > 3
|
|
280
294
|
or any(
|
|
281
|
-
not isinstance(item, dict) or set(item)
|
|
295
|
+
not isinstance(item, dict) or set(item) not in (audit_fields, repair_audit_fields)
|
|
282
296
|
or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
|
|
283
297
|
or not item["iteration"].isdigit() or int(item["iteration"]) < 1
|
|
284
298
|
or item["outcome"] not in {"planned", "submitted_for_recheck", "agent_failed", "agent_timed_out"}
|
|
285
299
|
or (item["commit_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["commit_sha"]))
|
|
300
|
+
or (set(item) == repair_audit_fields and (
|
|
301
|
+
not re.fullmatch(r"repair:[A-Za-z0-9_.:-]+:[1-3]", item["repair_id"])
|
|
302
|
+
or item["origin"] not in {"validation", "quality", "security", "hosted", "finalization"}
|
|
303
|
+
or (item["input_candidate_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["input_candidate_sha"]))
|
|
304
|
+
))
|
|
286
305
|
for item in state.repair_audit
|
|
287
306
|
)
|
|
307
|
+
or len({item.get("repair_id", f"legacy:{item['iteration']}") for item in state.repair_audit}) != len(state.repair_audit)
|
|
288
308
|
):
|
|
289
309
|
raise StateError("checkpoint repair audit is invalid or unsafe")
|
|
290
310
|
if (
|
|
@@ -357,6 +377,64 @@ class TransactionState:
|
|
|
357
377
|
)
|
|
358
378
|
):
|
|
359
379
|
raise StateError("checkpoint quality evidence is invalid or unsafe")
|
|
380
|
+
profile_fields = {"version", "digest", "candidate_sha"}
|
|
381
|
+
current_profile_fields = profile_fields | {"criteria_digest"}
|
|
382
|
+
if state.assurance_profile is not None and (
|
|
383
|
+
not isinstance(state.assurance_profile, dict)
|
|
384
|
+
or set(state.assurance_profile) not in (profile_fields, current_profile_fields)
|
|
385
|
+
or not all(isinstance(value, str) and value for value in state.assurance_profile.values())
|
|
386
|
+
or not re.fullmatch(r"sha256:[0-9a-f]{64}", state.assurance_profile["digest"])
|
|
387
|
+
or not re.fullmatch(r"[0-9a-f]{40}", state.assurance_profile["candidate_sha"])
|
|
388
|
+
):
|
|
389
|
+
raise StateError("checkpoint assurance profile is invalid")
|
|
390
|
+
review_fields = {"reviewer", "status", "candidate_sha", "profile_digest", "invocation_id", "findings"}
|
|
391
|
+
current_review_fields = review_fields | {"contract_version", "started_at", "completed_at"}
|
|
392
|
+
finding_fields = {"id", "fingerprint", "category", "criterion", "observation", "severity", "confidence", "blocking", "disposition"}
|
|
393
|
+
current_finding_fields = finding_fields | {"evidence_ref"}
|
|
394
|
+
if (
|
|
395
|
+
not isinstance(state.assurance_reviews, tuple)
|
|
396
|
+
or len(state.assurance_reviews) > 16
|
|
397
|
+
or any(
|
|
398
|
+
not isinstance(review, dict) or set(review) not in (review_fields, current_review_fields)
|
|
399
|
+
or review.get("reviewer") not in {"quality", "security"}
|
|
400
|
+
or review.get("status") not in {"PASS", "FAIL", "UNRESOLVED"}
|
|
401
|
+
or not isinstance(review.get("candidate_sha"), str) or not re.fullmatch(r"[0-9a-f]{40}", review["candidate_sha"])
|
|
402
|
+
or not isinstance(review.get("profile_digest"), str) or not re.fullmatch(r"sha256:[0-9a-f]{64}", review["profile_digest"])
|
|
403
|
+
or not isinstance(review.get("invocation_id"), str) or not review["invocation_id"]
|
|
404
|
+
or not isinstance(review.get("findings"), list) or len(review["findings"]) > 12
|
|
405
|
+
or any(
|
|
406
|
+
not isinstance(finding, dict) or set(finding) not in (finding_fields, current_finding_fields)
|
|
407
|
+
or not all(isinstance(value, str) and value and len(value) <= 240 and value == redact_diagnostic(value, limit=240) for key, value in finding.items() if key != "blocking")
|
|
408
|
+
or finding.get("severity") not in {"LOW", "MEDIUM", "HIGH", "CRITICAL"}
|
|
409
|
+
or finding.get("confidence") not in {"LOW", "MEDIUM", "HIGH"}
|
|
410
|
+
or finding.get("disposition") not in {"OPEN", "RESOLVED", "REJECTED", "NON_BLOCKING"}
|
|
411
|
+
or not isinstance(finding.get("blocking"), bool)
|
|
412
|
+
or ("evidence_ref" in finding and (not isinstance(finding["evidence_ref"], str) or not finding["evidence_ref"]))
|
|
413
|
+
for finding in review["findings"]
|
|
414
|
+
)
|
|
415
|
+
or (set(review) == current_review_fields and (
|
|
416
|
+
review.get("contract_version") != "1.0"
|
|
417
|
+
or not isinstance(review.get("started_at"), str)
|
|
418
|
+
or not isinstance(review.get("completed_at"), str)
|
|
419
|
+
))
|
|
420
|
+
for review in state.assurance_reviews
|
|
421
|
+
)
|
|
422
|
+
):
|
|
423
|
+
raise StateError("checkpoint assurance review evidence is invalid")
|
|
424
|
+
resolution_fields = {"finding_id", "disposition", "resolution_ref", "candidate_sha"}
|
|
425
|
+
if (
|
|
426
|
+
not isinstance(state.assurance_resolutions, tuple)
|
|
427
|
+
or len(state.assurance_resolutions) > 128
|
|
428
|
+
or any(
|
|
429
|
+
not isinstance(item, dict) or set(item) != resolution_fields
|
|
430
|
+
or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
|
|
431
|
+
or item["disposition"] not in {"RESOLVED", "REJECTED", "RISK_ACCEPTED"}
|
|
432
|
+
or not re.fullmatch(r"[0-9a-f]{40}", item["candidate_sha"])
|
|
433
|
+
for item in state.assurance_resolutions
|
|
434
|
+
)
|
|
435
|
+
or len({item["finding_id"] for item in state.assurance_resolutions}) != len(state.assurance_resolutions)
|
|
436
|
+
):
|
|
437
|
+
raise StateError("checkpoint assurance resolutions are invalid or unsafe")
|
|
360
438
|
if not isinstance(state.terminal, bool) or state.terminal != (state.phase in {"COMPLETE", "BLOCKED", "FAILED"}):
|
|
361
439
|
raise StateError("checkpoint terminal flag conflicts with phase")
|
|
362
440
|
return state
|
|
@@ -332,6 +332,7 @@ html[data-theme="light"] #promptHistory .execution-history-action{background:#ff
|
|
|
332
332
|
.confirmation-modal h2[data-modal-glyph="question"]::before{align-items:center;border:2px solid currentColor;border-radius:50%;box-sizing:border-box;display:inline-flex;height:var(--modal-title-glyph-size);justify-content:center;width:var(--modal-title-glyph-size);vertical-align:-.12em}
|
|
333
333
|
.confirmation-modal h2[data-modal-glyph="question"]::before{content:"?"}
|
|
334
334
|
.confirmation-modal h2[data-modal-glyph="warning"]::before{content:"⚠"}
|
|
335
|
+
.installation-relocation-modal h2[data-modal-glyph="warning"]::before{content:"!" !important}
|
|
335
336
|
.report-view-modal__title[data-modal-glyph="analysis"]::before{content:"✦"}
|
|
336
337
|
:is(.component-modal h2,.confirmation-modal h2,.report-view-modal__title,.prompt-detail-modal__header h2,.prompt-chat-modal__header h2){font-size:clamp(18px,2vw,20px);line-height:1.2}
|
|
337
338
|
|
|
@@ -850,6 +851,7 @@ html[data-theme="light"] .dashboard-modal-shell :is(.label,.field>.label){color:
|
|
|
850
851
|
actions therefore use the shared orange action language rather than blue. */
|
|
851
852
|
#operatorMergeWaitModal .dashboard-modal-shell__action{text-decoration:none}
|
|
852
853
|
#confirmationModal.dashboard-modal-shell--destructive .dashboard-modal-shell__action--destructive{background:#3a2028!important;border-color:#ff718f!important;color:#ffd9e1!important}#confirmationModal.dashboard-modal-shell--destructive .dashboard-modal-shell__action--destructive:hover:not(:disabled){background:#ff718f!important;border-color:#ff718f!important;color:#23131a!important}html[data-theme="light"] #confirmationModal.dashboard-modal-shell--destructive .dashboard-modal-shell__action--destructive{background:#fff1f4!important;border-color:#ff718f!important;color:#b32649!important}
|
|
854
|
+
#centralDataImportWarningModal .dashboard-modal-shell__action--destructive{background:#3a2028!important;border-color:#ff718f!important;color:#ffd9e1!important}#centralDataImportWarningModal .dashboard-modal-shell__action--destructive:hover:not(:disabled){background:#ff718f!important;border-color:#ff718f!important;color:#23131a!important}html[data-theme="light"] #centralDataImportWarningModal .dashboard-modal-shell__action--destructive{background:#fff1f4!important;border-color:#ff718f!important;color:#b32649!important}
|
|
853
855
|
#operatorMergeWaitModal .dashboard-modal-shell__action{border-color:#f0b66a!important;color:#fff0dc!important}#operatorMergeWaitModal .dashboard-modal-shell__action--primary{background:#3b281b!important;border-color:#f0b66a!important;color:#fff0dc!important}#operatorMergeWaitModal .dashboard-modal-shell__action--destructive{background:#3a2028!important;border-color:#ff718f!important;color:#ffd9e1!important}#operatorMergeWaitModal .dashboard-modal-shell__action--primary:hover:not(:disabled){background:var(--house-style)!important;border-color:var(--house-style)!important;color:var(--button-ink)!important}#operatorMergeWaitModal .dashboard-modal-shell__action--destructive:hover:not(:disabled){background:#ff718f!important;border-color:#ff718f!important;color:#23131a!important}html[data-theme="light"] #operatorMergeWaitModal .dashboard-modal-shell__action{background:#fff!important;border-color:#d68b23!important;color:#643a13!important}html[data-theme="light"] #operatorMergeWaitModal .dashboard-modal-shell__action--primary{background:#fff8ef!important}html[data-theme="light"] #operatorMergeWaitModal .dashboard-modal-shell__action--destructive{background:#fff1f4!important;border-color:#ff718f!important;color:#b32649!important}
|
|
854
856
|
/* Every modal uses a header tint derived from its own accent. The component
|
|
855
857
|
modal retains the same structure, with extra space below its ruler. */
|
|
@@ -869,7 +871,7 @@ html:not([data-theme="light"]) .dashboard-modal-shell{--modal-header-surface:col
|
|
|
869
871
|
.predecessor-retry::before{content:"↻";font:700 17px/1 system-ui;margin-right:8px;vertical-align:-1px}
|
|
870
872
|
.execution-dismiss::before{content:"⊘"}
|
|
871
873
|
#componentLogs .log-table{table-layout:auto;width:100%}#componentLogs .log-table th:last-child,#componentLogs .log-table td:last-child{width:100%}
|
|
872
|
-
#queueList .queue-item{grid-template-columns:1.25rem minmax(0,1fr) auto}.queue-defer{background:#3b281b;border:1px solid #f0b66a;border-radius:8px;color:#fff0dc;font:600 12px system-ui;min-height:32px;padding:5px 9px}.queue-defer:hover:not(:disabled){background:var(--house-style)!important;border-color:var(--house-style)!important;color:#201812!important}.queue-defer:disabled{cursor:wait;opacity:.7}html[data-theme="light"] .queue-defer{background:#fff8ef;border-color:#d68b23;color:#643a13}html[data-theme="light"] .queue-defer:hover:not(:disabled){background:var(--house-style)!important;border-color:var(--house-style)!important;color:#201812!important}
|
|
874
|
+
#queueList .queue-item{grid-template-columns:1.25rem minmax(0,1fr) auto}.queue-item__actions{align-items:flex-end;display:flex;flex-direction:column;gap:6px;justify-self:end}.queue-defer{background:#3b281b;border:1px solid #f0b66a;border-radius:8px;color:#fff0dc;font:600 12px system-ui;min-height:32px;padding:5px 9px}.queue-defer:hover:not(:disabled){background:var(--house-style)!important;border-color:var(--house-style)!important;color:#201812!important}.queue-defer:disabled{cursor:wait;opacity:.7}.queue-defer--destructive{background:#3a2028;border-color:#ff718f;color:#ffd9e1}.queue-defer--destructive:hover:not(:disabled){background:#ff718f!important;border-color:#ff718f!important;color:#23131a!important}html[data-theme="light"] .queue-defer{background:#fff8ef;border-color:#d68b23;color:#643a13}html[data-theme="light"] .queue-defer:hover:not(:disabled){background:var(--house-style)!important;border-color:var(--house-style)!important;color:#201812!important}html[data-theme="light"] .queue-defer--destructive{background:#fff1f4;border-color:#ff718f;color:#b32649}html[data-theme="light"] .queue-defer--destructive:hover:not(:disabled){background:#ff718f!important;border-color:#ff718f!important;color:#23131a!important}
|
|
873
875
|
|
|
874
876
|
/* Shared semantic action variants prevent individual surfaces from drifting. */
|
|
875
877
|
.dashboard-action{align-items:center;border:1px solid;border-radius:50%;box-sizing:border-box;display:inline-flex;font:18px/1 system-ui;height:32px;justify-content:center;min-height:32px;min-width:32px;padding:0;width:32px}
|
|
@@ -970,7 +972,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
|
|
|
970
972
|
/* Keep the input contract last: individual cards may colour their content,
|
|
971
973
|
but they must never replace the selected-control border. */
|
|
972
974
|
:where(input,select,textarea):is(:focus,:focus-visible){border-color:var(--dashboard-input-focus-border)!important;outline:var(--dashboard-focus-outline-width) solid var(--dashboard-input-focus-border)!important;outline-offset:var(--dashboard-focus-outline-offset)!important;box-shadow:0 0 0 var(--dashboard-focus-ring-size) var(--dashboard-input-focus-ring)!important}
|
|
973
|
-
:where(button,summary,[role="button"],[tabindex]):not(#engineering-dashboard-content):not(:where(.dashboard-modal-shell,.component-log-row,.prompt-history-row,.telemetry-row,.execution-lifecycle__node,.theme-toggle,.section-state-toggle,.auto-refresh-toggle,.log-sortable,.log-table-wrap,.telemetry-scroll,.telemetry-detail-table-scroll)):is(:focus,:focus-visible){outline:var(--dashboard-focus-outline-width) solid var(--dashboard-input-focus-border)!important;outline-offset:var(--dashboard-focus-outline-offset)!important;box-shadow:0 0 0 var(--dashboard-focus-ring-size) var(--dashboard-input-focus-ring)!important}
|
|
975
|
+
:where(button,summary,[role="button"],[tabindex]):not(#engineering-dashboard-content):not(:where(.dashboard-modal-shell,.component-log-row,.prompt-history-row,.telemetry-row,.execution-lifecycle__node,.local-folder-link,.theme-toggle,.section-state-toggle,.auto-refresh-toggle,.log-sortable,.log-table-wrap,.telemetry-scroll,.telemetry-detail-table-scroll)):is(:focus,:focus-visible){outline:var(--dashboard-focus-outline-width) solid var(--dashboard-input-focus-border)!important;outline-offset:var(--dashboard-focus-outline-offset)!important;box-shadow:0 0 0 var(--dashboard-focus-ring-size) var(--dashboard-input-focus-ring)!important}
|
|
974
976
|
/* Every dialog owns a full-viewport, safe-area-aware shell. The visible panel
|
|
975
977
|
is therefore always separated from iPhone edges, including modal families
|
|
976
978
|
added after the original report/detail implementations. */
|
|
@@ -994,8 +996,14 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
|
|
|
994
996
|
/* Relocation and component actions keep their position while optional actions change. */
|
|
995
997
|
.component-modal__actions{display:grid;gap:10px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:18px}.component-modal__actions .component-modal__restart{margin:0;min-height:44px;min-width:0;width:100%}.component-modal__actions .dashboard-modal-shell__action{grid-column:2;margin:0;min-width:0;width:100%}.installation-relocation-modal{padding:max(16px,env(safe-area-inset-top)) max(16px,env(safe-area-inset-right)) max(16px,env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left))!important}.installation-relocation-modal .dashboard-modal-shell__panel{display:grid;gap:18px;overflow:hidden}.installation-relocation-modal .dashboard-modal-shell__panel>p{margin:0}.installation-relocation-modal__locations{display:grid;gap:12px;margin:0}.installation-relocation-modal__locations div{display:grid;gap:4px}.installation-relocation-modal__locations dt{color:var(--modal-secondary-accent);font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase}.installation-relocation-modal__locations dd{margin:0;overflow-wrap:anywhere}.installation-relocation-modal .dashboard-modal-shell__actions{justify-content:flex-start;margin-top:0}.installation-relocation-modal .dashboard-modal-shell__action{min-width:10rem}.configuration-central-database__actions{align-items:center;display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end}
|
|
996
998
|
.footer__version-word{font-weight:400;text-transform:none}
|
|
999
|
+
#centralDataImportModal{--modal-panel-max-width:1100px}
|
|
1000
|
+
#centralDataImportStatus.configuration-central-data-import__error{color:#ff718f;font-weight:600}
|
|
1001
|
+
#centralDataImport::before{content:"↑"}
|
|
1002
|
+
#centralDataImportModal .dashboard-modal-shell__header h2::before{content:"↑"}
|
|
1003
|
+
#centralDatabaseRelocateModal .dashboard-modal-shell__header h2::before{content:"↗"}
|
|
1004
|
+
.installation-relocation-modal .dashboard-modal-shell__action:disabled{background:#35353d!important;border-color:#686873!important;color:#aaaab4!important;cursor:not-allowed}
|
|
997
1005
|
.installation-relocation-modal .dashboard-modal-shell__header{grid-template-columns:minmax(0,1fr) auto}.installation-relocation-modal .dashboard-modal-shell__header h2::before{content:"⚙︎";display:inline-block;font-size:20px;line-height:1;margin-right:.42em;vertical-align:-.04em}
|
|
998
|
-
.configuration-central-database__location-value{align-items:center;display:flex;flex-wrap:wrap;gap:10px}.configuration-central-database__location-link{flex:1 1 28rem}.configuration-central-database__export,.configuration-central-database__relocate{align-items:center;background-color:color-mix(in srgb,currentColor 14%,var(--dashboard-button-fill-surface));border:1px solid var(--house-style);border-radius:7px;color:var(--house-style);cursor:pointer;display:inline-flex;flex:none;font:600 13px/1 system-ui;gap:7px;min-height:34px;padding:7px 10px;text-decoration:none;white-space:nowrap}.configuration-central-database__export::before,.configuration-central-database__relocate::before{font-size:16px;font-weight:700;line-height:1}.configuration-central-database__export::before{content:"↓"}.configuration-central-database__relocate::before{content:"↗"}.configuration-central-database__export:hover:not(:disabled),.configuration-central-database__relocate:hover:not(:disabled){background:var(--house-style);color:var(--button-ink)}@media (max-width:620px){.configuration-central-database__export,.configuration-central-database__relocate{flex-basis:100%;justify-content:center}.configuration-central-database__location-link{flex-basis:100%}}
|
|
1006
|
+
.configuration-central-database__location-value{align-items:center;display:flex;flex-wrap:wrap;gap:10px}.configuration-central-database__location-link{flex:1 1 28rem}.configuration-central-database__export,.configuration-central-database__relocate{align-items:center;background-color:color-mix(in srgb,currentColor 14%,var(--dashboard-button-fill-surface));border:1px solid var(--house-style);border-radius:7px;box-sizing:border-box;color:var(--house-style);cursor:pointer;display:inline-flex;flex:none;font:600 13px/1 system-ui;gap:7px;min-height:34px;padding:7px 10px;text-decoration:none;white-space:nowrap}.configuration-central-database__export::before,.configuration-central-database__relocate::before{font-size:16px;font-weight:700;line-height:1}.configuration-central-database__export::before{content:"↓"}.configuration-central-database__relocate::before{content:"↗"}.configuration-central-database__export:hover:not(:disabled),.configuration-central-database__relocate:hover:not(:disabled){background:var(--house-style);color:var(--button-ink)}@media (max-width:620px){.configuration-central-database__export,.configuration-central-database__relocate{flex-basis:100%;justify-content:center}.configuration-central-database__location-link{flex-basis:100%}}
|
|
999
1007
|
.configuration-card :is(.configuration-provider-status h2,.configuration-validation-environment h3,.configuration-central-database__header h2,.configuration-server-settings h2,.configuration-readonly-settings h2,.configuration-timeout-policy h2,.configuration-controls h2,.configuration-dashboard-settings h2,.configuration-provider-login-status h2){font-size:16px;line-height:1.25}
|
|
1000
1008
|
/* A stored run-scoped conversation gets a filled, heavier history glyph. */
|
|
1001
1009
|
.prompt-history-chat--recorded{font-weight:800}
|
|
@@ -1036,7 +1044,7 @@ dialog.dashboard-modal-shell,dialog.dashboard-modal-shell:is(:focus,:focus-visib
|
|
|
1036
1044
|
every visible interactive focus treatment in the house-style orange,
|
|
1037
1045
|
including anchor actions inside dialogs. Deliberately non-focusing shells,
|
|
1038
1046
|
table-row selection surfaces and lifecycle geometry remain excluded above. */
|
|
1039
|
-
:where(a[href],button,input,select,textarea,[role="button"],[tabindex]):not(:where(.dashboard-modal-shell,.component-log-row,.prompt-history-row,.telemetry-row,.execution-lifecycle__node,.theme-toggle,.section-state-toggle,.auto-refresh-toggle,.log-sortable,.log-table-wrap,.telemetry-scroll,.telemetry-detail-table-scroll)):is(:focus,:focus-visible){border-color:var(--house-style)!important;outline-color:var(--house-style)!important;box-shadow:0 0 0 var(--dashboard-focus-ring-size) var(--dashboard-input-focus-ring)!important}
|
|
1047
|
+
:where(a[href],button,input,select,textarea,[role="button"],[tabindex]):not(:where(.dashboard-modal-shell,.component-log-row,.prompt-history-row,.telemetry-row,.execution-lifecycle__node,.local-folder-link,.theme-toggle,.section-state-toggle,.auto-refresh-toggle,.log-sortable,.log-table-wrap,.telemetry-scroll,.telemetry-detail-table-scroll)):is(:focus,:focus-visible){border-color:var(--house-style)!important;outline-color:var(--house-style)!important;box-shadow:0 0 0 var(--dashboard-focus-ring-size) var(--dashboard-input-focus-ring)!important}
|
|
1040
1048
|
/* Table scrollers are keyboard-scroll targets, not selected controls. Their
|
|
1041
1049
|
outer surface never receives a focus ring; only independently interactive
|
|
1042
1050
|
sortable headers retain their contained focus edge. */
|
|
@@ -1093,7 +1101,7 @@ html[data-theme="light"] .prompt-detail-modal__content .execution-lifecycle--his
|
|
|
1093
1101
|
.workspace-worktrees__active{color:#69e6ad;display:inline-block;font:700 14px/1 system-ui;margin-right:7px;vertical-align:1px}html[data-theme="light"] .workspace-worktrees__active{color:#187843}
|
|
1094
1102
|
/* Local paths remain text controls. Their only action is copying the displayed
|
|
1095
1103
|
path, so the dashboard neither opens Finder nor follows file:// URLs. */
|
|
1096
|
-
.local-folder-link{-webkit-appearance:none;appearance:none;background:transparent!important;border:0;color:var(--modal-secondary-accent)!important;cursor:pointer;font:inherit;overflow-wrap:anywhere;padding:0;text-align:left;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}.local-folder-link:is(:hover,:active,:focus,:focus-visible):not(:disabled){background:transparent!important;box-shadow:none!important;color:var(--modal-secondary-accent)!important;text-decoration-thickness:2px}.local-folder-link:
|
|
1104
|
+
.local-folder-link{-webkit-appearance:none;appearance:none;background:transparent!important;border:0;color:var(--modal-secondary-accent)!important;cursor:pointer;font:inherit;overflow-wrap:anywhere;padding:0;text-align:left;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}.local-folder-link:is(:hover,:active,:focus,:focus-visible):not(:disabled){background:transparent!important;box-shadow:none!important;color:var(--modal-secondary-accent)!important;outline:0!important;outline-offset:0!important;text-decoration-thickness:2px}.local-folder-link:disabled{cursor:default;opacity:1;text-decoration:none}.workspace-database__content .local-folder-link,.rate-limit-provider-path .local-folder-link{display:block;min-width:0;white-space:pre-wrap}
|
|
1097
1105
|
.runtime-directory-link{font-family:ui-monospace,SFMono-Regular,Menlo,monospace!important}
|
|
1098
1106
|
|
|
1099
1107
|
/* The Inbox location chooser inherits the exact indigo accent of its queue. */
|
|
@@ -1257,7 +1265,7 @@ html[data-theme="light"] #componentLogControls :is(input[type="date"],input[type
|
|
|
1257
1265
|
/* Controls whose visible shape is a pseudo-element or a native checkbox have
|
|
1258
1266
|
no normal border to recolour, so receive the same one-pixel edge directly. */
|
|
1259
1267
|
:is(.dashboard-titlebar .theme-toggle,.dashboard-titlebar .section-state-toggle):is(:focus,:focus-visible)::before,
|
|
1260
|
-
:is(.dashboard-health__button,.auto-refresh-toggle input
|
|
1268
|
+
:is(.dashboard-health__button,.auto-refresh-toggle input):is(:focus,:focus-visible){
|
|
1261
1269
|
box-shadow:none!important;
|
|
1262
1270
|
outline:1px solid var(--house-style)!important;
|
|
1263
1271
|
outline-offset:0!important;
|
|
@@ -1290,7 +1298,11 @@ html[data-theme="light"] #componentLogControls :is(input[type="date"],input[type
|
|
|
1290
1298
|
area. Do not add a later global bubble scroller: it would force short
|
|
1291
1299
|
messages to reserve scrollbar chrome and defeat the 2/3 area limit. */
|
|
1292
1300
|
@media (max-width:620px){.dashboard-status-banner{position:static}}
|
|
1293
|
-
.platform-attention{background:#5b4316;border-bottom:1px solid #f4c34f;color:#fff4d6;margin:0 0 18px}.platform-attention[hidden]{display:none}.platform-attention>summary{align-items:center;cursor:pointer;display:flex;gap:9px;list-style:none;padding:10px 16px}.platform-attention>summary::-webkit-details-marker{display:none}.platform-attention>summary::after{content:"▸";margin-left:auto}.platform-attention[open]>summary::after{content:"▾"}.platform-attention>summary strong{color:#ffd768}.platform-attention>summary span{background:#f4c34f;border-radius:999px;color:#2a2415;font-size:12px;font-weight:800;min-width:1.4rem;padding:2px 5px;text-align:center}.platform-attention__items{display:grid;gap:8px;padding:0 12px 12px}.platform-attention__items .dashboard-status-banner{margin:0;position:static}.platform-attention__items .dashboard-status-banner--provider-readiness{align-items:flex-start}.platform-attention__items .provider-readiness-banner__action{align-self:center}
|
|
1301
|
+
.platform-attention{background:#5b4316;border-bottom:1px solid #f4c34f;color:#fff4d6;margin:0 0 18px}.platform-attention[hidden]{display:none}.platform-attention>summary{align-items:center;cursor:pointer;display:flex;gap:9px;list-style:none;padding:10px 16px}.platform-attention>summary::-webkit-details-marker{display:none}.platform-attention>summary::after{content:"▸";font-size:24px;font-weight:700;line-height:1;margin-left:auto}.platform-attention[open]>summary::after{content:"▾"}.platform-attention>summary strong{color:#ffd768}.platform-attention>summary span{background:#f4c34f;border-radius:999px;color:#2a2415;font-size:12px;font-weight:800;min-width:1.4rem;padding:2px 5px;text-align:center}.platform-attention__items{display:grid;gap:8px;padding:0 12px 12px}.platform-attention__items .dashboard-status-banner{margin:0;position:static}.platform-attention__items .dashboard-status-banner--provider-readiness{align-items:flex-start}.platform-attention__items .provider-readiness-banner__action{align-self:center}
|
|
1302
|
+
|
|
1303
|
+
/* An expanded provider failure is its own red banner, not content inside an
|
|
1304
|
+
amber frame. Keep the amber summary, but leave the failure card unframed. */
|
|
1305
|
+
.platform-attention[open]{background:transparent;border:0}.platform-attention[open]>summary{background:#5b4316;border-bottom:1px solid #f4c34f}.platform-attention[open] .platform-attention__items{padding:8px 0 0}
|
|
1294
1306
|
|
|
1295
1307
|
/* Buttons are controls, not text links: every visible action gets a modest
|
|
1296
1308
|
fill derived from its own ink/border colour. Semantic local-file links and
|