@passioncode-ai/passioncode 0.2.48 → 0.2.49
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
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.49 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- On Windows the launcher makes its links (`current`, the skill hub and each agent's channel) as
|
|
8
|
+
junctions instead of symbolic links, so a member without an administrator session or Developer
|
|
9
|
+
Mode can install and update the skill set; a junction's target is read back in the same form the
|
|
10
|
+
launcher compares (PC-87).
|
|
11
|
+
|
|
3
12
|
## 0.2.48 - 2026-10-28
|
|
4
13
|
|
|
5
14
|
### Fixed
|
package/README.md
CHANGED
|
@@ -76,7 +76,8 @@ secret into a product's own hidden prompt, starting Docker for Fabric, and resta
|
|
|
76
76
|
comes from it.
|
|
77
77
|
- **Every other agent** (Cursor, Codex, Gemini, OpenCode, Kiro, Windsurf, Goose, …) gets
|
|
78
78
|
the same skills through `~/.agents/skills`, linked from each channel that exists on
|
|
79
|
-
the machine.
|
|
79
|
+
the machine. On Windows these links (and `~/.passioncode/current`) are junctions, which
|
|
80
|
+
need neither an administrator session nor Developer Mode.
|
|
80
81
|
- Updates create no skill copies in `~/.claude/skills`: a plain copy there shadows the plugin. Such
|
|
81
82
|
copies, and hub entries that pointed at a repository's working tree, are moved into
|
|
82
83
|
`~/.passioncode/quarantine/` — `npx @passioncode-ai/passioncode@latest restore` puts them back.
|
package/SECURITY.md
CHANGED
|
@@ -5,7 +5,7 @@ carries credentials or a working exploit.
|
|
|
5
5
|
|
|
6
6
|
What `passioncode update` touches (setup and doctor: [below](#what-setup-and-doctor-touch)): `~/.passioncode/` (releases, state, quarantine,
|
|
7
7
|
logs); Claude Code's plugin registry through the `claude plugin` CLI only;
|
|
8
|
-
`~/.agents/skills/<member skill>` and `<agent channel>/<member skill>` links; and
|
|
8
|
+
`~/.agents/skills/<member skill>` and `<agent channel>/<member skill>` links (junctions on Windows); and
|
|
9
9
|
`~/.claude/skills/<member skill>`, which it moves into the quarantine once the plugin
|
|
10
10
|
that replaces it is verified. For a member's old single-member marketplace
|
|
11
11
|
(`legacyMarketplaces` in `family.json`), once that plugin is verified and nothing else
|
package/lib/launcher.js
CHANGED
|
@@ -55,7 +55,25 @@ function writeText(file, text) {
|
|
|
55
55
|
fs.renameSync(tmp, file);
|
|
56
56
|
}
|
|
57
57
|
function lstat(p) { try { return fs.lstatSync(p); } catch (_) { return null; } }
|
|
58
|
-
|
|
58
|
+
/**
|
|
59
|
+
* A link's target as written. A Windows junction reads back absolute, sometimes behind `\\?\` or with a
|
|
60
|
+
* trailing separator, so there it is put in the form `path.resolve` gives (PC-87).
|
|
61
|
+
*/
|
|
62
|
+
function linkTarget(p) {
|
|
63
|
+
let target;
|
|
64
|
+
try { target = fs.readlinkSync(p); } catch (_) { return null; }
|
|
65
|
+
if (process.platform !== 'win32') return target;
|
|
66
|
+
target = target.replace(/^\\\\\?\\/, '');
|
|
67
|
+
return path.win32.isAbsolute(target) ? path.win32.resolve(target) : target;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Make a directory link. Windows makes a symbolic link only for an administrator or with Developer
|
|
71
|
+
* Mode on, so there it is a junction, which needs neither and always holds an absolute target (PC-87).
|
|
72
|
+
*/
|
|
73
|
+
function makeLink(target, at, { platform = process.platform, symlink = fs.symlinkSync } = {}) {
|
|
74
|
+
if (platform !== 'win32') return symlink(target, at);
|
|
75
|
+
return symlink(path.resolve(path.dirname(at), target), at, 'junction');
|
|
76
|
+
}
|
|
59
77
|
function pointsTo(at, target) { const link = linkTarget(at); return link !== null && path.resolve(path.dirname(at), link) === target; }
|
|
60
78
|
function isDirectory(at) { try { return fs.statSync(at).isDirectory(); } catch (_) { return false; } }
|
|
61
79
|
function readState(file, { tolerant = false } = {}) {
|
|
@@ -73,12 +91,13 @@ function readState(file, { tolerant = false } = {}) {
|
|
|
73
91
|
* On Windows the swap is therefore not atomic: between the unlink and the rename `at` is absent,
|
|
74
92
|
* and a run killed there leaves no `current` until the next update (status reports it missing).
|
|
75
93
|
*/
|
|
76
|
-
function symlinkAtomic(target, at, { platform = process.platform, rename = fs.renameSync, unlink = fs.unlinkSync } = {}) {
|
|
94
|
+
function symlinkAtomic(target, at, { platform = process.platform, rename = fs.renameSync, unlink = fs.unlinkSync, symlink = fs.symlinkSync } = {}) {
|
|
95
|
+
const link = (to, where) => makeLink(to, where, { platform, symlink });
|
|
77
96
|
fs.mkdirSync(path.dirname(at), { recursive: true });
|
|
78
97
|
const tmp = `${at}.${process.pid}.lnk`;
|
|
79
98
|
const dropTmp = () => { try { fs.unlinkSync(tmp); } catch (_) { /* none */ } };
|
|
80
99
|
dropTmp();
|
|
81
|
-
|
|
100
|
+
link(target, tmp);
|
|
82
101
|
try {
|
|
83
102
|
rename(tmp, at);
|
|
84
103
|
} catch (error) {
|
|
@@ -88,7 +107,7 @@ function symlinkAtomic(target, at, { platform = process.platform, rename = fs.re
|
|
|
88
107
|
try { unlink(at); } catch (unlinkError) { dropTmp(); throw unlinkError; }
|
|
89
108
|
try { rename(tmp, at); } catch (again) {
|
|
90
109
|
dropTmp();
|
|
91
|
-
try {
|
|
110
|
+
try { link(previous, at); } catch (back) { throw new Error(`${again.message}; and putting back ${at} → ${previous} failed (${back.message})`); }
|
|
92
111
|
throw again;
|
|
93
112
|
}
|
|
94
113
|
}
|
|
@@ -883,5 +902,5 @@ module.exports = {
|
|
|
883
902
|
restore: (opts = {}) => withUpdateLock(opts.home, () => restore(opts)),
|
|
884
903
|
uninstall: (opts = {}) => withUpdateLock(opts.home, () => uninstall(opts)),
|
|
885
904
|
status, setConfig, paths, CHANNELS, MARKETPLACE, payloadManifest, marketplaceAddArg,
|
|
886
|
-
acquireUpdateLock, UpdateRunning, staleReleases, symlinkAtomic, claudeRunner, bundledMcpServers, mcpFileTargets, readSettings, tomlTableRange, tomlTableCommand, tomlTableArgs, tomlMentions,
|
|
905
|
+
acquireUpdateLock, UpdateRunning, staleReleases, symlinkAtomic, makeLink, linkTarget, claudeRunner, bundledMcpServers, mcpFileTargets, readSettings, tomlTableRange, tomlTableCommand, tomlTableArgs, tomlMentions,
|
|
887
906
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.49",
|
|
4
4
|
"description": "Set up PassionCode.ai on a computer with one command — the apps from their verified releases, their MCP servers for every coding agent and the PassionCode.ai skills — and check and repair it with the same command or `doctor`.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"passioncode": "bin/passioncode.js"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"name": "passioncode",
|
|
36
36
|
"displayName": "PassionCode.ai",
|
|
37
37
|
"source": "./plugins/passioncode",
|
|
38
|
-
"version": "0.2.
|
|
38
|
+
"version": "0.2.49",
|
|
39
39
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
|
|
40
40
|
"author": {
|
|
41
41
|
"name": "PassionCode.ai",
|
package/payload/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"family": "passioncode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.49",
|
|
4
4
|
"release": true,
|
|
5
5
|
"members": [
|
|
6
6
|
{
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"name": "passioncode",
|
|
63
63
|
"displayName": "PassionCode.ai",
|
|
64
64
|
"repo": "passioncode-ai/passioncode",
|
|
65
|
-
"ref": "v0.2.
|
|
65
|
+
"ref": "v0.2.49",
|
|
66
66
|
"commit": null,
|
|
67
|
-
"version": "0.2.
|
|
67
|
+
"version": "0.2.49",
|
|
68
68
|
"via": "this repository",
|
|
69
69
|
"skills": [
|
|
70
70
|
"setting-up-passioncode",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
],
|
|
73
73
|
"legacyPluginIds": [],
|
|
74
74
|
"legacyMarketplaces": [],
|
|
75
|
-
"contentHash": "sha256:
|
|
75
|
+
"contentHash": "sha256:f69e173ef90a590a533a71de1028073a785e59d917a03c1bc0516cdba17698e2",
|
|
76
76
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check that keeps the PassionCode.ai set current.",
|
|
77
77
|
"author": {
|
|
78
78
|
"name": "PassionCode.ai",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "passioncode",
|
|
4
4
|
"displayName": "PassionCode.ai",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.49",
|
|
6
6
|
"description": "Set up and check PassionCode.ai on a computer with one command (setting-up-passioncode), the organisation's working rules for every contributor's agent (working-in-passioncode), and a once-a-day check at session start that keeps the PassionCode.ai skill set current.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "PassionCode.ai",
|