@indigoai-us/hq-cli 5.345.169 → 5.345.171
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.
- package/CHANGELOG.md +69 -0
- package/assets/scaffold/core/scripts/hq-delegate-send.sh +1 -1
- package/dist/command-catalog.generated.d.ts +181 -9
- package/dist/command-catalog.generated.js +224 -10
- package/dist/commands/access.d.ts +32 -1
- package/dist/commands/access.js +119 -5
- package/dist/commands/agent-kit.d.ts +1 -1
- package/dist/commands/agent-kit.js +3 -1
- package/dist/commands/agents.js +2 -1
- package/dist/commands/bot.d.ts +3 -0
- package/dist/commands/bot.js +141 -14
- package/dist/commands/cloud.d.ts +78 -1
- package/dist/commands/cloud.js +274 -9
- package/dist/commands/core-company-index-scope-flag.d.ts +8 -1
- package/dist/commands/core-company-index-scope-flag.js +9 -2
- package/dist/commands/core-delegate-w1b.js +5 -2
- package/dist/commands/core-dm-bind-native.js +19 -4
- package/dist/commands/core-rebuild-index-fast.js +24 -6
- package/dist/commands/core.js +18 -6
- package/dist/commands/dm.d.ts +17 -3
- package/dist/commands/dm.js +121 -26
- package/dist/commands/feedback-triage.d.ts +43 -1
- package/dist/commands/feedback-triage.js +123 -23
- package/dist/commands/feedback.d.ts +40 -1
- package/dist/commands/feedback.js +184 -4
- package/dist/commands/files.d.ts +42 -0
- package/dist/commands/files.js +223 -30
- package/dist/commands/integrations-api.d.ts +4 -0
- package/dist/commands/integrations-api.js +18 -2
- package/dist/commands/integrations-connect.d.ts +10 -3
- package/dist/commands/integrations-connect.js +70 -6
- package/dist/commands/integrations-core.d.ts +23 -0
- package/dist/commands/integrations-core.js +100 -0
- package/dist/commands/integrations-manage.js +8 -1
- package/dist/commands/integrations.js +49 -5
- package/dist/commands/lanes-loop.d.ts +20 -0
- package/dist/commands/lanes-loop.js +69 -11
- package/dist/commands/lanes.js +9 -1
- package/dist/commands/mesh.js +6 -0
- package/dist/commands/rescue.d.ts +9 -0
- package/dist/commands/rescue.js +31 -0
- package/dist/commands/run.js +115 -40
- package/dist/commands/scan.d.ts +5 -1
- package/dist/commands/scan.js +16 -4
- package/dist/commands/secrets.js +50 -9
- package/dist/commands/sync-manifest.d.ts +16 -0
- package/dist/commands/sync-manifest.js +17 -1
- package/dist/hq-cloud-sync-runner/bin/sync-runner.js +2367 -2109
- package/dist/hq-cloud-sync-runner/package.json +1 -1
- package/dist/lib/agent-kit/inbox-state.d.ts +17 -0
- package/dist/lib/agent-kit/inbox-state.js +41 -20
- package/dist/lib/agent-kit/kit-config.d.ts +2 -0
- package/dist/lib/agent-kit/kit-config.js +6 -0
- package/dist/lib/agent-kit/mcp/tools.js +12 -5
- package/dist/lib/agent-kit/run/heartbeat.d.ts +6 -3
- package/dist/lib/agent-kit/run/heartbeat.js +6 -3
- package/dist/lib/agent-kit/run/inbox.d.ts +8 -3
- package/dist/lib/agent-kit/run/inbox.js +42 -10
- package/dist/lib/agent-kit/run/request-timeout.d.ts +26 -0
- package/dist/lib/agent-kit/run/request-timeout.js +51 -0
- package/dist/lib/bot/api.d.ts +1 -1
- package/dist/lib/bot/config.d.ts +10 -0
- package/dist/lib/bot/config.js +17 -1
- package/dist/lib/bot/decisions.d.ts +62 -0
- package/dist/lib/bot/decisions.js +228 -0
- package/dist/lib/bot/fleet-local.d.ts +127 -0
- package/dist/lib/bot/fleet-local.js +638 -0
- package/dist/lib/bot/index.d.ts +2 -0
- package/dist/lib/bot/index.js +2 -0
- package/dist/lib/bot/local-config.d.ts +3 -2
- package/dist/lib/bot/local-config.js +5 -2
- package/dist/lib/bot/promote.d.ts +10 -0
- package/dist/lib/bot/promote.js +3 -2
- package/dist/lib/bot/run.d.ts +7 -0
- package/dist/lib/bot/run.js +104 -1
- package/dist/lib/bot/runtime/index.js +8 -4
- package/dist/lib/bot/runtime/scratch-dir.d.ts +24 -0
- package/dist/lib/bot/runtime/scratch-dir.js +41 -0
- package/dist/lib/caller-principal.d.ts +4 -0
- package/dist/lib/caller-principal.js +40 -0
- package/dist/lib/capacity/collectors/grok.js +8 -2
- package/dist/lib/cli-flag-keys.d.ts +2 -0
- package/dist/lib/cli-flag-keys.js +2 -0
- package/dist/lib/daemon/catalog.d.ts +4 -0
- package/dist/lib/daemon/catalog.js +63 -29
- package/dist/lib/daemon/config.d.ts +7 -0
- package/dist/lib/daemon/config.js +32 -0
- package/dist/lib/daemon/run.d.ts +3 -2
- package/dist/lib/daemon/run.js +23 -3
- package/dist/lib/daemon/supervisor.d.ts +1 -0
- package/dist/lib/daemon/supervisor.js +4 -0
- package/dist/lib/daemon/sync-core-canary.d.ts +12 -0
- package/dist/lib/daemon/sync-core-canary.js +61 -0
- package/dist/lib/doctor/checks/release-links.d.ts +62 -1
- package/dist/lib/doctor/checks/release-links.js +188 -2
- package/dist/lib/doctor/checks/sync-health.d.ts +32 -0
- package/dist/lib/doctor/checks/sync-health.js +54 -1
- package/dist/lib/doctor/fix/apply.d.ts +26 -4
- package/dist/lib/doctor/fix/apply.js +149 -11
- package/dist/lib/doctor/fix/remediation.d.ts +8 -1
- package/dist/lib/doctor/fix/remediation.js +22 -0
- package/dist/lib/doctor/types.d.ts +1 -1
- package/dist/lib/doctor/types.js +1 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/index-render/index.d.ts +9 -0
- package/dist/lib/index-render/index.js +65 -5
- package/dist/lib/index-render/session-scope.d.ts +69 -0
- package/dist/lib/index-render/session-scope.js +279 -0
- package/dist/lib/lanes/admission.js +7 -20
- package/dist/lib/lanes/reconcile.js +13 -15
- package/dist/lib/lanes/stale-lock.d.ts +50 -0
- package/dist/lib/lanes/stale-lock.js +105 -0
- package/dist/lib/lanes/store.js +11 -76
- package/dist/lib/mesh/live/daemon/work-subscribe.js +31 -0
- package/dist/lib/notify-recipient.d.ts +10 -4
- package/dist/lib/notify-recipient.js +16 -4
- package/dist/lib/secret-input-link.d.ts +42 -0
- package/dist/lib/secret-input-link.js +93 -0
- package/dist/lib/secret-scan/range.d.ts +57 -0
- package/dist/lib/secret-scan/range.js +266 -0
- package/dist/lib/secret-scan/repo-config.d.ts +18 -3
- package/dist/lib/secret-scan/repo-config.js +135 -2
- package/dist/lib/work-context/organize.d.ts +7 -0
- package/dist/lib/work-context/organize.js +21 -1
- package/dist/run/script-bound-schema.d.ts +27 -0
- package/dist/run/script-bound-schema.js +97 -0
- package/dist/secrets-env-action.d.ts +2 -0
- package/dist/secrets-env-action.js +7 -2
- package/dist/sentry-before-send.js +1 -0
- package/dist/utils/cognito-session.d.ts +3 -30
- package/dist/utils/cognito-session.js +2 -100
- package/dist/utils/machine-principal-state.d.ts +38 -0
- package/dist/utils/machine-principal-state.js +110 -0
- package/dist/utils/safe-link.js +9 -0
- package/dist/utils/script-bound-exec.d.ts +158 -0
- package/dist/utils/script-bound-exec.js +568 -0
- package/dist/utils/sync-watchdog.d.ts +92 -0
- package/dist/utils/sync-watchdog.js +250 -0
- package/package.json +8 -8
|
@@ -44,6 +44,7 @@ import { getStateDir } from "@indigoai-us/hq-cloud";
|
|
|
44
44
|
import { isPersonalJournalSlug } from "../checks/sync-health.js";
|
|
45
45
|
import { createDefaultRegistry } from "../registry.js";
|
|
46
46
|
import { flattenFamilies } from "../report.js";
|
|
47
|
+
import { repairDanglingReleaseLinks } from "../checks/release-links.js";
|
|
47
48
|
import { parseHookGateProfiles, requiredMissingProfiles, } from "../hook-gate-profiles.js";
|
|
48
49
|
import { createBackup } from "./backup.js";
|
|
49
50
|
import { removeStrayGateEntries } from "../stray-gate-entries.js";
|
|
@@ -735,20 +736,95 @@ function defaultLocksDir() {
|
|
|
735
736
|
export const REFRESH_SYNC_LOCK_TIMEOUT_SEC = 30;
|
|
736
737
|
/**
|
|
737
738
|
* Default `refresh-manifest` repair: a bounded `hq sync manifest --scope <s>`
|
|
738
|
-
* against the tree `--fix` is repairing
|
|
739
|
-
*
|
|
740
|
-
*
|
|
739
|
+
* against the tree `--fix` is repairing, with `--json` so a pass that exits 0
|
|
740
|
+
* without uploading (soft_skipped, throttled, disabled, locked,
|
|
741
|
+
* resend_full_scheduled) is reported as not uploaded. A `resend_full` answer
|
|
742
|
+
* is retried once with `--full`. The post-fix re-check still decides whether
|
|
743
|
+
* the row cleared. A timeout or non-zero exit is reported, not thrown.
|
|
741
744
|
*/
|
|
742
745
|
export function defaultRefreshManifest(target) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
746
|
+
return Promise.resolve(refreshManifestWithRetry(target.scope, (full, json) => {
|
|
747
|
+
const hqBin = process.argv[1];
|
|
748
|
+
const args = [
|
|
749
|
+
"sync",
|
|
750
|
+
"manifest",
|
|
751
|
+
"--scope",
|
|
752
|
+
target.scope,
|
|
753
|
+
"--hq-root",
|
|
754
|
+
target.hqRoot,
|
|
755
|
+
...(json ? ["--json"] : []),
|
|
756
|
+
...(full ? ["--full"] : []),
|
|
757
|
+
];
|
|
758
|
+
return spawnSync(hqBin ? process.execPath : "hq", hqBin ? [hqBin, ...args] : args, {
|
|
759
|
+
encoding: "utf8",
|
|
760
|
+
timeout: REFRESH_SYNC_TIMEOUT_MS,
|
|
761
|
+
cwd: target.hqRoot,
|
|
762
|
+
});
|
|
763
|
+
}));
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Run one upload and, when the server answered `resend_full` (it dropped or
|
|
767
|
+
* refused the delta base), run it once more with `--full`. Without the retry
|
|
768
|
+
* the scope stays stale until the next day's --fix run, and the health hook
|
|
769
|
+
* reports it as unrepaired in between (feedback_84d7a862).
|
|
770
|
+
*/
|
|
771
|
+
export function refreshManifestWithRetry(scope, run) {
|
|
772
|
+
const firstRaw = run(false, true);
|
|
773
|
+
// `hq` from PATH can be an older binary without `--json`. Fall back to the
|
|
774
|
+
// exit-code handling it always had instead of reporting a failure.
|
|
775
|
+
if (manifestJsonUnsupported(firstRaw))
|
|
776
|
+
return manifestUploadResult(scope, run(false, false));
|
|
777
|
+
const first = manifestUploadResult(scope, firstRaw);
|
|
778
|
+
if (first.passStatus !== "resend_full_scheduled")
|
|
779
|
+
return first;
|
|
780
|
+
const retry = manifestUploadResult(scope, run(true, true));
|
|
781
|
+
if (retry.passStatus !== "resend_full_scheduled")
|
|
782
|
+
return retry;
|
|
783
|
+
return {
|
|
784
|
+
...retry,
|
|
785
|
+
reason: "the server asked for a full manifest again after a --full retry; a full resend is queued, so run `hq sync` again later",
|
|
786
|
+
};
|
|
751
787
|
}
|
|
788
|
+
/** Commander's rejection of `--json` by a binary that predates it. */
|
|
789
|
+
export function manifestJsonUnsupported(result) {
|
|
790
|
+
if (result.status === 0 || result.status === null)
|
|
791
|
+
return false;
|
|
792
|
+
return /unknown option ['"]?--json/i.test(`${result.stderr ?? ""}\n${result.stdout ?? ""}`);
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* The status token from the `hq sync manifest --json` line, or undefined when
|
|
796
|
+
* the output has none (an older binary, or a pass that printed only a summary).
|
|
797
|
+
*/
|
|
798
|
+
export function manifestPassStatus(stdout) {
|
|
799
|
+
const lines = (stdout ?? "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
800
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
801
|
+
const line = lines[index];
|
|
802
|
+
if (!line.startsWith("{"))
|
|
803
|
+
continue;
|
|
804
|
+
try {
|
|
805
|
+
const parsed = JSON.parse(line);
|
|
806
|
+
if (typeof parsed.status === "string" && /^[a-z_]{1,40}$/.test(parsed.status)) {
|
|
807
|
+
return parsed.status;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
catch {
|
|
811
|
+
// Not the outcome line.
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return undefined;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Plain-words reason for a pass that exited 0 without uploading. Each one
|
|
818
|
+
* leaves `lastUploadAt` unchanged, so the stale row cannot clear.
|
|
819
|
+
*/
|
|
820
|
+
const MANIFEST_NOT_UPLOADED_REASONS = {
|
|
821
|
+
soft_skipped: "the sync service did not accept manifest uploads (the pass was skipped)",
|
|
822
|
+
throttled: "the pass was throttled and sent nothing",
|
|
823
|
+
disabled: "manifest uploads are turned off on this machine",
|
|
824
|
+
locked: "another manifest pass for this scope was already running",
|
|
825
|
+
resend_full_scheduled: "the server asked for a fresh full manifest and the upload did not finish",
|
|
826
|
+
printed: "the pass only printed the manifest",
|
|
827
|
+
};
|
|
752
828
|
/**
|
|
753
829
|
* Map one `hq sync manifest` spawn result to a {@link RefreshManifestResult}.
|
|
754
830
|
* A spawn killed by the timeout has a null status, so it is reported as a
|
|
@@ -778,6 +854,15 @@ export function manifestUploadResult(scope, result) {
|
|
|
778
854
|
: {}),
|
|
779
855
|
};
|
|
780
856
|
}
|
|
857
|
+
const passStatus = manifestPassStatus(result.stdout);
|
|
858
|
+
if (passStatus && passStatus !== "uploaded") {
|
|
859
|
+
return {
|
|
860
|
+
ok: false,
|
|
861
|
+
passStatus,
|
|
862
|
+
reason: MANIFEST_NOT_UPLOADED_REASONS[passStatus] ?? `the pass ended '${passStatus}' without uploading`,
|
|
863
|
+
message: `manifest upload for '${scope}' did not upload (${passStatus})`,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
781
866
|
return { ok: true, message: `uploaded the manifest for '${scope}'` };
|
|
782
867
|
}
|
|
783
868
|
/** `hq sync manifest` output for a company this identity is not a member of. */
|
|
@@ -821,6 +906,8 @@ function planFix(hqRoot, result, rem, refreshSync, rewriteBotNodePath = defaultR
|
|
|
821
906
|
return planRefreshSync(hqRoot, result, rem, refreshSync);
|
|
822
907
|
case "refresh-manifest":
|
|
823
908
|
return planRefreshManifest(hqRoot, result, rem, refreshManifest);
|
|
909
|
+
case "repair-release-link":
|
|
910
|
+
return planRepairReleaseLink(hqRoot, result, rem);
|
|
824
911
|
default:
|
|
825
912
|
return null;
|
|
826
913
|
}
|
|
@@ -991,6 +1078,57 @@ function planRefreshManifest(hqRoot, result, rem, refreshManifest) {
|
|
|
991
1078
|
failureReason: () => failureReason,
|
|
992
1079
|
};
|
|
993
1080
|
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Repoint (or remove) one dangling HQ-managed release link. The repair writes
|
|
1083
|
+
* only the link entry, never a hook body, so it needs no backup: a link that
|
|
1084
|
+
* does not resolve has no content to restore.
|
|
1085
|
+
*/
|
|
1086
|
+
function planRepairReleaseLink(hqRoot, result, rem) {
|
|
1087
|
+
const rel = rem.fixTarget;
|
|
1088
|
+
if (!rel)
|
|
1089
|
+
return null;
|
|
1090
|
+
let failure;
|
|
1091
|
+
return {
|
|
1092
|
+
checkId: result.checkId,
|
|
1093
|
+
fixClass: "repair-release-link",
|
|
1094
|
+
target: rel,
|
|
1095
|
+
relpath: "",
|
|
1096
|
+
preview: ` ${rel}\n` +
|
|
1097
|
+
` - dangling link\n` +
|
|
1098
|
+
` + the shipped link to its target under the HQ root (removed if that target is missing)`,
|
|
1099
|
+
summary: `repair dangling link ${rel}`,
|
|
1100
|
+
apply: () => {
|
|
1101
|
+
// Each plan repairs only its own link, and a throw is recorded as this
|
|
1102
|
+
// plan's failure so the remaining plans still run.
|
|
1103
|
+
try {
|
|
1104
|
+
const own = repairDanglingReleaseLinks(hqRoot, { only: rel });
|
|
1105
|
+
const entry = own.find((item) => item.rel === rel);
|
|
1106
|
+
if (!entry) {
|
|
1107
|
+
failure = `${rel} was not repaired`;
|
|
1108
|
+
}
|
|
1109
|
+
else if (entry.action === "skipped" || entry.action === "failed") {
|
|
1110
|
+
failure = `${rel} was not repaired: ${entry.reason ?? entry.action}`;
|
|
1111
|
+
}
|
|
1112
|
+
else {
|
|
1113
|
+
failure = undefined;
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
catch (err) {
|
|
1117
|
+
failure = `${rel} was not repaired: ${err instanceof Error ? err.message : String(err)}`;
|
|
1118
|
+
}
|
|
1119
|
+
},
|
|
1120
|
+
postStatus: (results) => {
|
|
1121
|
+
const own = results.filter((entry) => entry.checkId === result.checkId);
|
|
1122
|
+
if (own.some((entry) => entry.target === rel))
|
|
1123
|
+
return "FAIL";
|
|
1124
|
+
// Another link's failure is that plan's status, not this one's.
|
|
1125
|
+
if (own.some((entry) => entry.status === "FAIL"))
|
|
1126
|
+
return "PASS";
|
|
1127
|
+
return own[0]?.status ?? null;
|
|
1128
|
+
},
|
|
1129
|
+
failureReason: () => failure,
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
994
1132
|
/** Restore the execute bit on a hook script. */
|
|
995
1133
|
function planExecutableBit(hqRoot, result, rem) {
|
|
996
1134
|
const abs = rem.fixTarget;
|
|
@@ -43,6 +43,13 @@
|
|
|
43
43
|
* hq-cli shim (see `lib/windows/ps1-shims.ts`); the
|
|
44
44
|
* execution policy is never changed. This is the one
|
|
45
45
|
* scoped exception to the no-delete rule below.
|
|
46
|
+
* - `repair-release-link` — repoint an HQ-managed release link
|
|
47
|
+
* (`.agents/skills`, `.codex/claude`, ...) whose target
|
|
48
|
+
* is missing, using the link text HQ ships (absolute junction on Windows).
|
|
49
|
+
* When that target is missing too, the dangling link
|
|
50
|
+
* entry is removed. Only a link that does not resolve
|
|
51
|
+
* is touched; a real file or folder never is, and the
|
|
52
|
+
* link is removed without following it.
|
|
46
53
|
*
|
|
47
54
|
* EVERYTHING else — content drift between platform copies, a missing script, a
|
|
48
55
|
* missing Codex counterpart, an unquoted `$CLAUDE_PROJECT_DIR`, a stale
|
|
@@ -54,7 +61,7 @@
|
|
|
54
61
|
*/
|
|
55
62
|
import type { CheckResult } from "../types.js";
|
|
56
63
|
/** The allowlisted safe repair classes `--fix` is permitted to apply. */
|
|
57
|
-
export type FixClass = "executable-bit" | "gate-profile" | "remove-stray-gate-entries" | "refresh-sync" | "refresh-manifest" | "bot-node-path" | "bot-hq-binary" | "remove-ps1-shims";
|
|
64
|
+
export type FixClass = "executable-bit" | "gate-profile" | "remove-stray-gate-entries" | "refresh-sync" | "refresh-manifest" | "bot-node-path" | "bot-hq-binary" | "remove-ps1-shims" | "repair-release-link";
|
|
58
65
|
/**
|
|
59
66
|
* A finding's structured remediation. `autoFixable`, `action`, and `command`
|
|
60
67
|
* are the `--json` surface (AC1); `fixTarget`/`fixClass` are the internal handle
|
|
@@ -43,6 +43,13 @@
|
|
|
43
43
|
* hq-cli shim (see `lib/windows/ps1-shims.ts`); the
|
|
44
44
|
* execution policy is never changed. This is the one
|
|
45
45
|
* scoped exception to the no-delete rule below.
|
|
46
|
+
* - `repair-release-link` — repoint an HQ-managed release link
|
|
47
|
+
* (`.agents/skills`, `.codex/claude`, ...) whose target
|
|
48
|
+
* is missing, using the link text HQ ships (absolute junction on Windows).
|
|
49
|
+
* When that target is missing too, the dangling link
|
|
50
|
+
* entry is removed. Only a link that does not resolve
|
|
51
|
+
* is touched; a real file or folder never is, and the
|
|
52
|
+
* link is removed without following it.
|
|
46
53
|
*
|
|
47
54
|
* EVERYTHING else — content drift between platform copies, a missing script, a
|
|
48
55
|
* missing Codex counterpart, an unquoted `$CLAUDE_PROJECT_DIR`, a stale
|
|
@@ -53,6 +60,7 @@
|
|
|
53
60
|
* deciding which of two diverged copies is correct needs human judgement.
|
|
54
61
|
*/
|
|
55
62
|
import * as path from "node:path";
|
|
63
|
+
import { DANGLING_RELEASE_LINK_PROBLEM, RELEASE_LINKS, RELEASE_LINKS_CHECK_ID, } from "../checks/release-links.js";
|
|
56
64
|
import { isCompanyJournalSlug, isSafeCompanySlug, isPersonalJournalSlug, journalSlugFromCheckId, } from "../checks/sync-health.js";
|
|
57
65
|
/** Matches an exec-bit remediation command, quoted or not: `chmod +x <path>`. */
|
|
58
66
|
const CHMOD_EXEC = /^chmod\s+\+x\s+(.+)$/;
|
|
@@ -165,6 +173,20 @@ export function deriveRemediation(result) {
|
|
|
165
173
|
command: "hq.cmd install --global",
|
|
166
174
|
};
|
|
167
175
|
}
|
|
176
|
+
// repair-release-link — a shipped link whose target is missing, such as one
|
|
177
|
+
// a rescue pointed at its deleted temp folder (feedback_2ab63e50).
|
|
178
|
+
if (checkId === RELEASE_LINKS_CHECK_ID &&
|
|
179
|
+
result.status === "FAIL" &&
|
|
180
|
+
RELEASE_LINKS.some((entry) => entry.rel === target) &&
|
|
181
|
+
result.message.startsWith(target + " " + DANGLING_RELEASE_LINK_PROBLEM)) {
|
|
182
|
+
return {
|
|
183
|
+
autoFixable: true,
|
|
184
|
+
fixClass: "repair-release-link",
|
|
185
|
+
fixTarget: target,
|
|
186
|
+
action: `Repoint the dangling ${target} link at its target under the HQ root (or remove the link when that target is missing).`,
|
|
187
|
+
command: "hq doctor --fix",
|
|
188
|
+
};
|
|
189
|
+
}
|
|
168
190
|
// Available hq-core upgrade. WARN is intentional in `hq doctor` and is
|
|
169
191
|
// not a broken sync; --fix has no mechanical repair for it.
|
|
170
192
|
if (checkId === "sync.update.core") {
|
|
@@ -19,7 +19,7 @@ export declare const DOCTOR_STATUSES: readonly ["PASS", "FAIL", "WARN", "UNTESTE
|
|
|
19
19
|
*/
|
|
20
20
|
export type DoctorStatus = (typeof DOCTOR_STATUSES)[number];
|
|
21
21
|
/** Stable, privacy-safe diagnostics emitted by the sync health family. */
|
|
22
|
-
export declare const SYNC_REASON_CODES: readonly ["core-version-unavailable", "core-update-available", "no-local-tree", "company-not-resolved", "legacy-personal-journal", "never-synced", "invalid-last-sync", "stale-threshold", "refresh-in-progress", "refresh-lock-held", "manifest-unavailable", "manifest-state-unavailable", "no-manifest-scopes", "never-uploaded", "invalid-upload-time", "unresolved-company-uid", "realtime-lag-stuck", "receiver-permission-denied", "pull-access-denied", "runner-restart-loop", "device-limit-backoff", "repeated-conflicts"];
|
|
22
|
+
export declare const SYNC_REASON_CODES: readonly ["core-version-unavailable", "core-update-available", "no-local-tree", "company-not-resolved", "legacy-personal-journal", "never-synced", "invalid-last-sync", "stale-threshold", "refresh-in-progress", "refresh-lock-held", "manifest-unavailable", "manifest-state-unavailable", "no-manifest-scopes", "never-uploaded", "invalid-upload-time", "manifest-upload-rejected", "unresolved-company-uid", "realtime-lag-stuck", "receiver-permission-denied", "pull-access-denied", "runner-restart-loop", "device-limit-backoff", "repeated-conflicts"];
|
|
23
23
|
export type SyncReasonCode = (typeof SYNC_REASON_CODES)[number];
|
|
24
24
|
/** Runtime type guard: true only for a member of the fixed vocabulary. */
|
|
25
25
|
export declare function isDoctorStatus(value: unknown): value is DoctorStatus;
|
package/dist/lib/doctor/types.js
CHANGED