happyskills 0.27.1 → 0.27.2
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 +6 -0
- package/package.json +1 -1
- package/src/commands/publish.js +2 -1
- package/src/commands/refresh.js +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.27.2] - 2026-04-02
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Fix `publish` not syncing dependency declarations to the lock file when publishing an existing skill — the lock entry's `dependencies` field was stale after publish
|
|
14
|
+
- Fix `refresh` not detecting dependency drift — skills whose lock `dependencies` diverged from the installed `skill.json` were incorrectly reported as up-to-date because the staleness check was purely commit-based
|
|
15
|
+
|
|
10
16
|
## [0.27.1] - 2026-04-02
|
|
11
17
|
|
|
12
18
|
### Fixed
|
package/package.json
CHANGED
package/src/commands/publish.js
CHANGED
|
@@ -229,7 +229,8 @@ const run = (args) => catch_errors('Publish failed', async () => {
|
|
|
229
229
|
ref: push_data?.ref || `refs/tags/v${manifest.version}`,
|
|
230
230
|
commit: push_data?.commit || null,
|
|
231
231
|
base_commit: push_data?.commit || null,
|
|
232
|
-
base_integrity: (!hash_err && integrity) ? integrity : null
|
|
232
|
+
base_integrity: (!hash_err && integrity) ? integrity : null,
|
|
233
|
+
dependencies: manifest.dependencies || {}
|
|
233
234
|
}
|
|
234
235
|
if (!hash_err && integrity) updated_entry.integrity = integrity
|
|
235
236
|
delete updated_entry.merge_parents
|
package/src/commands/refresh.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { error: { catch_errors, wrap_errors: e } } = require('puffy-core')
|
|
2
2
|
const { install } = require('../engine/installer')
|
|
3
3
|
const { read_lock, get_all_locked_skills } = require('../lock/reader')
|
|
4
|
+
const { read_manifest } = require('../manifest/reader')
|
|
4
5
|
const { detect_status } = require('../merge/detector')
|
|
5
6
|
const repos_api = require('../api/repos')
|
|
6
7
|
const { print_help, print_table, print_json, print_info, print_success, print_warn, print_hint, code } = require('../ui/output')
|
|
@@ -26,6 +27,16 @@ Examples:
|
|
|
26
27
|
happyskills refresh -y
|
|
27
28
|
happyskills refresh -g -y --json`
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Returns true if the lock entry's dependencies differ from the installed skill.json's dependencies.
|
|
32
|
+
*/
|
|
33
|
+
const has_dependency_drift = (lock_entry, manifest) => {
|
|
34
|
+
if (!manifest) return false
|
|
35
|
+
const lock_deps = JSON.stringify(lock_entry.dependencies || {})
|
|
36
|
+
const manifest_deps = JSON.stringify(manifest.dependencies || {})
|
|
37
|
+
return lock_deps !== manifest_deps
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
const confirm_prompt = (question) => new Promise((resolve) => {
|
|
30
41
|
const readline = require('readline')
|
|
31
42
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr })
|
|
@@ -72,6 +83,15 @@ const run = (args) => catch_errors('Refresh failed', async () => {
|
|
|
72
83
|
}
|
|
73
84
|
} else {
|
|
74
85
|
spinner?.succeed('Checked for updates')
|
|
86
|
+
const base_dir = skills_dir(is_global, project_root)
|
|
87
|
+
// Read all installed manifests in parallel to check for dependency drift
|
|
88
|
+
const manifest_map = {}
|
|
89
|
+
await Promise.all(to_check.map(async ([name]) => {
|
|
90
|
+
const short_name = name.split('/')[1] || name
|
|
91
|
+
const dir = skill_install_dir(base_dir, short_name)
|
|
92
|
+
const [, manifest] = await read_manifest(dir)
|
|
93
|
+
if (manifest) manifest_map[name] = manifest
|
|
94
|
+
}))
|
|
75
95
|
for (const [name, data] of to_check) {
|
|
76
96
|
const info = batch_data?.results?.[name]
|
|
77
97
|
if (info?.access_denied) {
|
|
@@ -83,6 +103,9 @@ const run = (args) => catch_errors('Refresh failed', async () => {
|
|
|
83
103
|
} else if (!data.base_commit && info.latest_version !== data.version) {
|
|
84
104
|
// Fallback to version comparison for old lock files without base_commit
|
|
85
105
|
results.push({ skill: name, installed: data.version, latest: info.latest_version, status: 'outdated' })
|
|
106
|
+
} else if (has_dependency_drift(data, manifest_map[name])) {
|
|
107
|
+
// Lock dependencies are stale compared to installed skill.json
|
|
108
|
+
results.push({ skill: name, installed: data.version, latest: info.latest_version, status: 'outdated' })
|
|
86
109
|
} else {
|
|
87
110
|
results.push({ skill: name, installed: data.version, latest: info.latest_version, status: 'up-to-date' })
|
|
88
111
|
}
|