mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-08 19:06:04 +00:00
fix(cli): make skills update converge on a skill retired upstream (#2176)
`hyperframes skills update` failed hard or looped forever once a skill was
retired/renamed upstream while still installed locally (hyperframes-media folded
into media-use; hyperframes-captions/compose/tts consolidated earlier). Two
paths dead-ended:
- Install: target selection could trust a stale local skills-manifest.json
(findRepoManifest) while `skills add` always installs from the canonical repo.
isCoreSkill matches the `hyperframes-` prefix, so a retired skill was forced
into the target set, `skills add` silently declined it (exit 0), and strict
verifyInstalled threw "Skill(s) still missing after install".
- Prune: upstream `skills remove` scans on-disk directories, so a lock entry
retired before it ever shipped a bundle has nothing to match — a silent
exit-0 no-op that never clears the lock, so detectRemoved re-flags it on
every run.
The stale-skills nudge compounded it: it fired even from `skills update` itself
(pointing users back at the failing command) and its count ignored the removed
bucket.
Resolve update targets against the canonical manifest (checkSkills({ canonical:
true })) so a retired skill is never targeted. Add pruneOrphanedLockEntries to
clear the orphaned lock entries the upstream remover can't (idempotent, so a
second run is a clean no-op). Exclude `skills` from the update-nudge gate and
thread the removed count through the nudge total.
This commit is contained in:
@@ -16,6 +16,8 @@ export interface SkillsUpdateMeta {
|
||||
updateAvailable: boolean;
|
||||
outdated: number;
|
||||
missing: number;
|
||||
/** Installed skills flagged removed-upstream (renamed/dropped) at the last check. */
|
||||
removed: number;
|
||||
}
|
||||
|
||||
/** Synchronous read from cache — never fetches. */
|
||||
@@ -25,6 +27,7 @@ function getSkillsUpdateMeta(): SkillsUpdateMeta {
|
||||
updateAvailable: config.skillsUpdateAvailable ?? false,
|
||||
outdated: config.skillsOutdatedCount ?? 0,
|
||||
missing: config.skillsMissingCount ?? 0,
|
||||
removed: config.skillsRemovedCount ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,7 +38,10 @@ function cacheFresh(lastSkillsCheck: string | undefined, now: number): boolean {
|
||||
|
||||
/** Run the real check and persist the result to the cache. */
|
||||
async function refreshSkillsCache(): Promise<SkillsUpdateMeta> {
|
||||
const result = await checkSkills();
|
||||
// `canonical: true` so this nudge's counts agree with `updateSkills`'s
|
||||
// source of truth — otherwise a stale in-repo skills-manifest.json (e.g.
|
||||
// inside a hyperframes checkout) can produce a false-positive count here.
|
||||
const result = await checkSkills({ canonical: true });
|
||||
// Only record a meaningful check when skills were actually found.
|
||||
if (result.location) {
|
||||
const config = readConfig();
|
||||
@@ -45,12 +51,18 @@ async function refreshSkillsCache(): Promise<SkillsUpdateMeta> {
|
||||
// Core-missing only: skills that install on demand (workflows not yet
|
||||
// triggered on this machine) are not "missing" worth nagging about.
|
||||
config.skillsMissingCount = result.summary.coreMissing;
|
||||
// Removed-upstream skills are just as reconcilable as outdated/missing
|
||||
// ones (a plain `skills update` prunes them) — omitting them here is what
|
||||
// made the nudge undercount (e.g. reporting "2 skills out of date or
|
||||
// missing" while a 3rd, renamed/dropped skill sat unmentioned).
|
||||
config.skillsRemovedCount = result.summary.removed;
|
||||
writeConfig(config);
|
||||
}
|
||||
return {
|
||||
updateAvailable: result.updateAvailable,
|
||||
outdated: result.summary.outdated,
|
||||
missing: result.summary.coreMissing,
|
||||
removed: result.summary.removed,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,9 +82,9 @@ export async function checkSkillsForUpdate(force?: boolean): Promise<SkillsUpdat
|
||||
}
|
||||
}
|
||||
|
||||
/** The stale-skills nudge text, or null when nothing is outdated or missing. */
|
||||
/** The stale-skills nudge text, or null when nothing is outdated, missing, or removed. */
|
||||
function skillsNoticeText(meta: SkillsUpdateMeta): string | null {
|
||||
const total = meta.outdated + meta.missing;
|
||||
const total = meta.outdated + meta.missing + meta.removed;
|
||||
if (total < 1) return null;
|
||||
const noun = total === 1 ? "skill" : "skills";
|
||||
return `\n ${total} HyperFrames ${noun} out of date or missing.\n Run: npx hyperframes skills update\n\n`;
|
||||
|
||||
Reference in New Issue
Block a user