diff --git a/.codex/skills/design-vpn-client-ui/SKILL.md b/.codex/skills/design-vpn-client-ui/SKILL.md
index 9c52afa..3df0fe2 100644
--- a/.codex/skills/design-vpn-client-ui/SKILL.md
+++ b/.codex/skills/design-vpn-client-ui/SKILL.md
@@ -18,6 +18,15 @@ Preserve the repo's focused one-screen VPN client language: a centered primary a
7. Implement `prefers-reduced-motion` alongside every new animation.
8. Run `npm test`, `npm run build`, and `git diff --check`. Perform manual visual inspection only when explicitly requested.
+## Communicating a proposed change
+
+For implementation proposals and progress summaries, combine structure instead of maximizing it:
+
+- start with one compact table grouped by affected modules such as frontend, UI, backend/API, styles, tests, and versions;
+- use short lists only for cross-cutting details such as states, accessibility, motion, or changed files;
+- keep unaffected modules visible in the table when that clarifies scope;
+- avoid both an unstructured paragraph and a separate table for every subsection.
+
## Non-negotiable decisions
- Keep the power action on the screen's central vertical axis. Place subscription content to its right without shifting that axis.
diff --git a/AGENTS.md b/AGENTS.md
index 866bb7e..d2addc8 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -4,4 +4,6 @@ Use the checked-in `workpack/` directory as the only roadmap source. Do not requ
Follow `workpack/AGENTS.md` for every roadmap task, including status updates. Completed tasks must not be selected or implemented again unless the user explicitly asks to reopen one.
+Before implementing any feature, record or refresh its plan in the selected `workpack/tasks/TASK-*.md` file using the mandatory feature-plan contract from `workpack/AGENTS.md`. Write the whole plan in simple language understandable without knowledge of the codebase: explain technical terms on first use, and use file paths or code names only as supporting detail. The plan must explain the implementation sequence and affected system components. For user-visible work it must also specify layout and states, exact icons, animation/motion behavior, accessibility and reduced-motion behavior; otherwise it must explicitly state that UI, icons and motion are unaffected. A proposed visible design is not owner approval.
+
For every runtime, UI, API, dependency or deployment-config change, use `.codex/skills/manage-harbor-versions/SKILL.md`. Before completion, classify the affected components, bump the required version level and run `npm run version:harbor -- check `. Documentation- and test-only changes do not require a bump.
diff --git a/src/shared/versions.ts b/src/shared/versions.ts
index 89803a9..bbfe9b7 100644
--- a/src/shared/versions.ts
+++ b/src/shared/versions.ts
@@ -1,6 +1,6 @@
export const HARBOR_VERSIONS = Object.freeze({
- macClient: '0.26.6',
- gatewayClient: '0.27.6',
+ macClient: '0.26.7',
+ gatewayClient: '0.27.7',
gatewayBackend: '0.27.0',
});
diff --git a/src/web/features/diagnostics/ConnectivityDiagnosticsPanel.tsx b/src/web/features/diagnostics/ConnectivityDiagnosticsPanel.tsx
index 4b8a676..f752afd 100644
--- a/src/web/features/diagnostics/ConnectivityDiagnosticsPanel.tsx
+++ b/src/web/features/diagnostics/ConnectivityDiagnosticsPanel.tsx
@@ -109,6 +109,34 @@ function Status({ value, route }: { value: StatusValue; route: string }) {
;
}
+function RowRefresh({
+ label,
+ running,
+ disabled,
+ onRun,
+}: {
+ label: string;
+ running: boolean;
+ disabled: boolean;
+ onRun: () => void;
+}) {
+ return
+
+ Проверить только эту строку
+ ;
+}
+
function ipResult(path: DiagnosticPath | undefined, source: IpSourceDefinition) {
if (!path?.available) return null;
return source.family === 6
@@ -222,6 +250,7 @@ export function ConnectivityDiagnosticsPanel({
const sheetRef = useRef(null);
const runnerRef = useRef(null);
const previousTargetRef = useRef(null);
+ const retryTargetRef = useRef(undefined);
const requestError = requestDetails(error);
useEffect(() => {
@@ -264,12 +293,13 @@ export function ConnectivityDiagnosticsPanel({
previousTargetRef.current = activeTarget;
}, [activeTarget]);
- async function run() {
+ async function run(onlyTarget?: string) {
+ retryTargetRef.current = onlyTarget;
setStatus('running');
setError(null);
try {
let next = result;
- const targets = [
+ const targets = onlyTarget ? [onlyTarget] : [
CONNECTIVITY_NETWORK_SOURCE.id,
...CONNECTIVITY_IP_SOURCES.map(({ id }) => `ip:${id}`),
...sites.map(({ id }) => `site:${id}`),
@@ -379,7 +409,7 @@ export function ConnectivityDiagnosticsPanel({
aria-label="Проверить маршруты"
aria-busy={pending}
disabled={pending}
- onClick={run}
+ onClick={() => run()}
>