@passioncode-ai/passioncode 0.2.51 → 0.2.53
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 +25 -0
- package/README.md +3 -2
- package/SECURITY.md +1 -1
- package/bin/passioncode.js +2 -2
- package/lib/doctor.js +8 -8
- package/lib/releases.js +1 -1
- package/lib/setup.js +32 -14
- package/package.json +2 -2
- package/payload/.claude-plugin/marketplace.json +1 -1
- package/payload/manifest.json +4 -4
- package/payload/plugins/passioncode/.claude-plugin/plugin.json +1 -1
- package/payload/plugins/passioncode/hooks/update-check.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.53 - 2026-11-02
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- What the launcher prints for a person carries no em dash (PC-95): the `setup` install question, its
|
|
8
|
+
app verification lines and its "Your steps" header, the `doctor` details and fixes for Node, a stopped
|
|
9
|
+
app, Docker, the Supabase CLI, MCP registrations and proving calls, and services, the `help` title,
|
|
10
|
+
the `update` closing line, and the session-start update notices. A
|
|
11
|
+
colon, comma, semicolon or parentheses take its place. Each line keeps its meaning, except that the
|
|
12
|
+
"Your steps" header no longer says an agent cannot do any of them (some are commands an agent runs):
|
|
13
|
+
it now reads "sign-ins, consents and secrets in hidden prompts need you in person". A test now
|
|
14
|
+
fails on an em dash, or its escape, in any string under `bin/`, `lib/` or the plugin's hooks. The npm
|
|
15
|
+
description and the GitHub release title (now "PassionCode.ai <tag>") carry none either.
|
|
16
|
+
|
|
17
|
+
## 0.2.52 - 2026-11-02
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `setup` in a terminal, answered "no" to every offer (at least one of them defaulting to yes) and so
|
|
22
|
+
changing nothing, says "You declined every offer; nothing was changed." instead of "Everything this
|
|
23
|
+
command can set up is in place" (or "Nothing to do." when it named a train), and a release train named in that run is reported as not saved without the
|
|
24
|
+
advice to answer in a terminal (PC-91). Forgetting a train with `--train none` is still a change.
|
|
25
|
+
Such a run now lists `setup` among the person's steps when a failing or warning check's own fix
|
|
26
|
+
names it (`setup --train <name>` when the run declined that train).
|
|
27
|
+
|
|
3
28
|
## 0.2.51 - 2026-10-30
|
|
4
29
|
|
|
5
30
|
### Fixed
|
package/README.md
CHANGED
|
@@ -118,8 +118,9 @@ the versions in [`trains/organization-r1.json`](trains/organization-r1.json), re
|
|
|
118
118
|
and `doctor` then compares every app with its pin (offline too) in an `app.<id>` line per app and
|
|
119
119
|
one `train` line. An app newer than its pin is reported and left alone (a damaged one, or one whose version cannot be read, is reinstalled from the latest
|
|
120
120
|
release): the train never takes an app back, because its data may not open in an older release. `setup --train none` returns to the
|
|
121
|
-
latest releases. Either change is saved with `--yes` or in a terminal; without both it is only
|
|
122
|
-
|
|
121
|
+
latest releases. Either change is saved with `--yes` or in a terminal; without both it is only shown as a plan. A named
|
|
122
|
+
train is not saved when every offer in the terminal (at least one of them defaulting to yes) is
|
|
123
|
+
answered no, while `--train none` is saved on any answer. The skills are pinned by the launcher release itself (`family.json`). Which
|
|
123
124
|
version each app pins is the train's record in fabric-workspace
|
|
124
125
|
([SD-4](https://github.com/passioncode-ai/fabric-workspace/blob/main/knowledge/roadmap.md#sd-4)); a
|
|
125
126
|
change to the file is a launcher release.
|
package/SECURITY.md
CHANGED
|
@@ -72,7 +72,7 @@ The hook installs a newer version on its own only when all of these hold:
|
|
|
72
72
|
It then runs `npx --yes @passioncode-ai/passioncode@<that exact version> update --quiet`, detached, so
|
|
73
73
|
the version that was checked is the version that runs. In every other case it spawns
|
|
74
74
|
nothing: a version from an account outside the list is reported in one line naming the
|
|
75
|
-
account ("… not a trusted PassionCode publisher
|
|
75
|
+
account ("… not a trusted PassionCode publisher, so it is not installed"); a name nobody has
|
|
76
76
|
published (npm E404) is silent; a failed check is shown once.
|
|
77
77
|
|
|
78
78
|
The current allowlist lives in [`plugin/passioncode/trust.json`](plugin/passioncode/trust.json).
|
package/bin/passioncode.js
CHANGED
|
@@ -17,7 +17,7 @@ function cachedNpmStatus({ latest, checkedAt, installed }) {
|
|
|
17
17
|
return `npm latest (cached) ${latest} (${checked}${stale ? '; stale: older than installed' : ''})`;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const HELP = `passioncode
|
|
20
|
+
const HELP = `passioncode sets up and checks PassionCode.ai on this machine: the apps, their MCP servers, the skills
|
|
21
21
|
|
|
22
22
|
npx @passioncode-ai/passioncode@latest setup [--yes] [--with ids] [--without ids] [--train name|none] [--no-apps] [--no-open] [--dry-run] [--json]
|
|
23
23
|
a new machine: install and configure everything; an existing one: check, repair, check again
|
|
@@ -126,7 +126,7 @@ async function main(argv) {
|
|
|
126
126
|
out(r, [
|
|
127
127
|
...r.steps.map((s) => `${s.outcome.padEnd(8)} ${s.kind.padEnd(11)} ${s.detail}${s.error ? `\n ${s.error}` : ''}`),
|
|
128
128
|
'',
|
|
129
|
-
failed.length ? `${failed.length} step(s) failed. Completed steps remain applied. Fix the cause and retry; use passioncode restore for displaced files.` : rest.includes('--dry-run') ? `Plan for PassionCode.ai ${r.version}: nothing was changed.` : `PassionCode.ai ${r.version}: done. Restart your agent
|
|
129
|
+
failed.length ? `${failed.length} step(s) failed. Completed steps remain applied. Fix the cause and retry; use passioncode restore for displaced files.` : rest.includes('--dry-run') ? `Plan for PassionCode.ai ${r.version}: nothing was changed.` : `PassionCode.ai ${r.version}: done. Restart your agent: skills load at session start.`,
|
|
130
130
|
r.moved.length ? `${r.moved.length} recovery entry(s) saved; use \`passioncode restore\`.` : '',
|
|
131
131
|
].filter(Boolean).join('\n'));
|
|
132
132
|
}
|
package/lib/doctor.js
CHANGED
|
@@ -151,7 +151,7 @@ async function collect({ home, platform, claude, online, train: trainName }) {
|
|
|
151
151
|
|
|
152
152
|
// Prerequisites and agents.
|
|
153
153
|
const major = Number(process.versions.node.split('.')[0]);
|
|
154
|
-
add({ id: 'prereq.node', area: 'prerequisites', state: major >= 18 ? 'ok' : 'fail', detail: `Node ${process.versions.node}${major >= 18 ? '' : '
|
|
154
|
+
add({ id: 'prereq.node', area: 'prerequisites', state: major >= 18 ? 'ok' : 'fail', detail: `Node ${process.versions.node}${major >= 18 ? '' : ' (18 or newer is needed)'}`, fix: major >= 18 ? null : 'install Node 18+ from https://nodejs.org' });
|
|
155
155
|
const agents = presentAgents(home, claude);
|
|
156
156
|
add({ id: 'prereq.agents', area: 'prerequisites', state: agents.length ? 'ok' : 'warn', detail: agents.length ? `coding agents: ${agents.map((a) => a.name).join(', ')}` : 'no coding agent found (Claude Code, Codex CLI, Gemini CLI or Kimi Code)', fix: agents.length ? null : 'install Claude Code: npm install -g @anthropic-ai/claude-code' });
|
|
157
157
|
|
|
@@ -243,15 +243,15 @@ async function collect({ home, platform, claude, online, train: trainName }) {
|
|
|
243
243
|
}
|
|
244
244
|
const v = releases.verifyApp(at, { gatekeeper: false });
|
|
245
245
|
add({ id: `app.${pr.id}.signature`, area: 'apps', product: pr.id, state: v.ok ? 'ok' : 'fail', detail: `${pr.name}: ${v.checks.map((c) => `${c.check} ${c.ok ? 'ok' : `FAILED (${c.detail})`}`).join(', ')}`, fix: v.ok ? null : (running ? `quit ${pr.name}, then run \`${NPX} setup\`` : `${NPX} setup`), repair: !v.ok && !running ? { kind: 'replace', product: pr.id } : null });
|
|
246
|
-
add({ id: `app.${pr.id}.running`, area: 'apps', product: pr.id, state: 'info', detail: `${pr.name}: ${running ? 'in use (the app, or an agent\'s MCP server from its bundle)' : 'not running (it starts when opened)'}`, fix: running ? null : `open "${at}"
|
|
246
|
+
add({ id: `app.${pr.id}.running`, area: 'apps', product: pr.id, state: 'info', detail: `${pr.name}: ${running ? 'in use (the app, or an agent\'s MCP server from its bundle)' : 'not running (it starts when opened)'}`, fix: running ? null : `open "${at}", or ask this machine's app supervisor to start it` });
|
|
247
247
|
if (pr.needs && pr.needs.includes('docker')) {
|
|
248
248
|
docker = docker || releases.run('docker', ['info', '--format', '{{.ServerVersion}}'], { timeout: 15000 });
|
|
249
249
|
const missing = docker.code === 127;
|
|
250
|
-
add({ id: 'prereq.docker', area: 'prerequisites', product: pr.id, state: docker.code === 0 ? 'ok' : missing ? 'fail' : 'warn', detail: docker.code === 0 ? `Docker answers (server ${docker.out.trim()})` : missing ? 'Docker is not installed
|
|
250
|
+
add({ id: 'prereq.docker', area: 'prerequisites', product: pr.id, state: docker.code === 0 ? 'ok' : missing ? 'fail' : 'warn', detail: docker.code === 0 ? `Docker answers (server ${docker.out.trim()})` : missing ? 'Docker is not installed; Fabric needs it' : 'Docker is installed but not running; Fabric needs it running', fix: docker.code === 0 ? null : missing ? 'install OrbStack (https://orbstack.dev) or Docker Desktop, then start it' : 'start OrbStack or Docker Desktop before you open Fabric' });
|
|
251
251
|
}
|
|
252
252
|
if (pr.needs && pr.needs.includes('supabase')) {
|
|
253
253
|
const sb = releases.run('supabase', ['--version'], { timeout: 15000 });
|
|
254
|
-
add({ id: 'prereq.supabase', area: 'prerequisites', product: pr.id, state: sb.code === 0 ? 'ok' : 'fail', detail: sb.code === 0 ? `Supabase CLI ${sb.out.trim()}` : 'Supabase CLI not found
|
|
254
|
+
add({ id: 'prereq.supabase', area: 'prerequisites', product: pr.id, state: sb.code === 0 ? 'ok' : 'fail', detail: sb.code === 0 ? `Supabase CLI ${sb.out.trim()}` : 'Supabase CLI not found; Fabric needs it', fix: sb.code === 0 ? null : 'brew install supabase/tap/supabase' });
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
|
|
@@ -285,7 +285,7 @@ async function collect({ home, platform, claude, online, train: trainName }) {
|
|
|
285
285
|
const runner = entry.args.includes('--runner');
|
|
286
286
|
add({
|
|
287
287
|
id, area: 'mcp', product: pr.id, state: exec && runner ? 'ok' : 'fail',
|
|
288
|
-
detail: `${agent.name}: ${m.name} ${exec && runner ? 'registered; doctor does not start it (it enrols a session)
|
|
288
|
+
detail: `${agent.name}: ${m.name} ${exec && runner ? 'registered; doctor does not start it (it enrols a session), and your agent\'s first fabric_whoami proves it' : !exec ? `points at ${entry.command}, which cannot run` : 'is registered without --runner, so it exits at start'}`,
|
|
289
289
|
fix: exec && runner ? null : `remove that entry from ${agent.name}, then ${NPX} setup`,
|
|
290
290
|
});
|
|
291
291
|
continue;
|
|
@@ -333,7 +333,7 @@ async function collect({ home, platform, claude, online, train: trainName }) {
|
|
|
333
333
|
const what = tool ? `${tool} answered` : 'initialize answered (its first real call is the agent\'s)';
|
|
334
334
|
add({
|
|
335
335
|
id, area: 'mcp', product: t.product.id, state: r.ok ? 'ok' : 'fail',
|
|
336
|
-
detail: `${agent.name}: ${t.product.mcp.name}
|
|
336
|
+
detail: `${agent.name}: ${t.product.mcp.name}, ${r.ok ? `${what}${r.server ? ` (${r.server.name} ${r.server.version || ''})`.replace(' )', ')') : ''}${r.tools !== null && r.tools !== undefined ? `, ${r.tools} tools` : ''}` : `proving call failed: ${r.reason}`}`,
|
|
337
337
|
fix: r.ok ? null : `open ${t.product.name}, then run doctor again; if it still fails, reinstall it from ${t.product.page}`,
|
|
338
338
|
});
|
|
339
339
|
}
|
|
@@ -358,8 +358,8 @@ async function collect({ home, platform, claude, online, train: trainName }) {
|
|
|
358
358
|
add({
|
|
359
359
|
id: `service.${d.id}.${d.instance || 'default'}`, area: 'services', product: pr.id,
|
|
360
360
|
state: w.ok === true ? (w.status === 'ok' ? 'ok' : 'warn') : w.ok === null ? 'info' : 'fail',
|
|
361
|
-
detail: `${d.name || d.id}: ${w.ok ? `answers at ${d.origin}${w.version ? ` (${w.version})` : ''}, status ${w.status}${w.degraded.length ?
|
|
362
|
-
fix: w.ok === false ? `${supervisor} restarts it
|
|
361
|
+
detail: `${d.name || d.id}: ${w.ok ? `answers at ${d.origin}${w.version ? ` (${w.version})` : ''}, status ${w.status}${w.degraded.length ? `; degraded: ${w.degraded.join(', ')}` : ''}` : w.reason}`,
|
|
362
|
+
fix: w.ok === false ? `${supervisor} restarts it, so never kill it by hand${doctorCmd ? `; diagnose with ${doctorCmd}` : ''}` : (w.ok && w.status !== 'ok' && doctorCmd ? doctorCmd : null),
|
|
363
363
|
repair: w.ok === false && platform === 'darwin' && d.lifecycle && d.lifecycle.manager === 'launchd' && d.lifecycle.label ? { kind: 'kickstart', label: d.lifecycle.label } : null,
|
|
364
364
|
});
|
|
365
365
|
}
|
package/lib/releases.js
CHANGED
|
@@ -217,7 +217,7 @@ async function installApp(product, release, { work, report = () => {}, replace =
|
|
|
217
217
|
}
|
|
218
218
|
if (!source) throw new Error(`${assetName} holds no ${product.app}`);
|
|
219
219
|
const app = verifyApp(source);
|
|
220
|
-
for (const c of app.checks) report({ kind: 'verify', detail: `${product.app}
|
|
220
|
+
for (const c of app.checks) report({ kind: 'verify', detail: `${product.app}, ${c.check}: ${c.detail}`, ok: c.ok });
|
|
221
221
|
if (!app.ok) throw new Error(`${product.app} failed ${app.checks.filter((c) => !c.ok).map((c) => c.check).join(', ')}; nothing was installed`);
|
|
222
222
|
// Copy beside the target first, so /Applications never holds a half-written bundle; then two
|
|
223
223
|
// same-volume renames: the old bundle to the person's Trash (never deleted), the new one into place.
|
package/lib/setup.js
CHANGED
|
@@ -137,7 +137,7 @@ async function setup({
|
|
|
137
137
|
asked = true;
|
|
138
138
|
for (const i of items.filter((x) => x.kind === 'install')) {
|
|
139
139
|
const pr = catalog.byId(i.product);
|
|
140
|
-
i.selected = await yesNo(ask, `Install ${pr.name}${pr.preview ? ' (early preview)' : ''}${i.note ?
|
|
140
|
+
i.selected = await yesNo(ask, `Install ${pr.name}${pr.preview ? ' (early preview)' : ''}${i.note ? `: ${i.note}` : ''}?`, i.selected);
|
|
141
141
|
}
|
|
142
142
|
const repairs = items.filter((x) => x.kind !== 'install');
|
|
143
143
|
if (repairs.length) {
|
|
@@ -148,13 +148,18 @@ async function setup({
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
// The train is saved by a run the person agreed to: --yes, or answers in a terminal. Without
|
|
151
|
-
// either nothing changes, whatever the plan. A person who answered no to every offer
|
|
152
|
-
// to yes declined a named train too; forgetting one (`none`) touches no app, so any answer saves
|
|
151
|
+
// either nothing changes, whatever the plan. A person who answered no to every offer (at least one of
|
|
152
|
+
// them defaulting to yes) declined a named train too; forgetting one (`none`) touches no app, so any answer saves
|
|
153
153
|
// it: it is the way out of a saved train this launcher cannot use.
|
|
154
154
|
const declinedAll = asked && offeredYes.length > 0 && !items.some((i) => i.selected);
|
|
155
155
|
// A named train declined with everything else changes nothing; its checks (made for that train)
|
|
156
156
|
// are not saved as this machine's state either.
|
|
157
|
-
if (trainName && declinedAll && changesTrain) {
|
|
157
|
+
if (trainName && declinedAll && changesTrain) {
|
|
158
|
+
result.planOnly = true; result.declined = true; result.trainNotSaved = trainName;
|
|
159
|
+
// Its checks were made for the train it declined: what fixes them is setup with that train.
|
|
160
|
+
result.humanSteps = humanSteps(result, before, items, [], noApps, `${D.NPX} setup --train ${trainName}`);
|
|
161
|
+
return finish(result, home, before);
|
|
162
|
+
}
|
|
158
163
|
if (changesTrain) { // the train already saved is left as it is: nothing to write
|
|
159
164
|
const was = D.trainOf(home).id;
|
|
160
165
|
saveTrain(home, trainName);
|
|
@@ -166,6 +171,10 @@ async function setup({
|
|
|
166
171
|
}
|
|
167
172
|
}
|
|
168
173
|
|
|
174
|
+
// Said so in the report: an empty run after "no" to every offer is not a machine with nothing to set
|
|
175
|
+
// up. Forgetting a train (`--train none`) is still a change, so that run is not "declined".
|
|
176
|
+
if (declinedAll && !result.actions.length) result.declined = true;
|
|
177
|
+
|
|
169
178
|
const act = (kind, detail, product = null) => {
|
|
170
179
|
const a = { kind, detail, product, outcome: 'done' };
|
|
171
180
|
result.actions.push(a);
|
|
@@ -226,16 +235,24 @@ async function setup({
|
|
|
226
235
|
const after = result.actions.length ? D.sortChecks(await D.collect({ home, platform, claude, online })) : before;
|
|
227
236
|
result.after = { checks: after, summary: D.summarise(after) };
|
|
228
237
|
|
|
229
|
-
|
|
230
|
-
|
|
238
|
+
result.humanSteps = humanSteps(result, after, items, installed, noApps);
|
|
239
|
+
return finish(result, home, after);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// The person's steps, once: every remaining problem's fix, the guides of the apps just installed,
|
|
243
|
+
// what an install leaves to a person, and a restart when skills or MCP servers changed.
|
|
244
|
+
function humanSteps(result, after, items, installed, noApps, setupStep = `${D.NPX} setup`) {
|
|
231
245
|
const steps = [];
|
|
232
246
|
const push = (t) => { if (t && !steps.includes(t)) steps.push(t); };
|
|
233
247
|
const anyFailed = result.actions.some((x) => x.outcome === 'failed');
|
|
234
248
|
for (const c of after) {
|
|
235
249
|
if (!(c.state === 'fail' || c.state === 'warn') || !c.fix) continue;
|
|
236
|
-
if (c.fix === `${D.NPX} setup` && !anyFailed && !result.planOnly && !noApps) continue; // this run was that command
|
|
250
|
+
if (c.fix === `${D.NPX} setup` && !anyFailed && !result.planOnly && !noApps && !result.declined) continue; // this run was that command (unless it was declined)
|
|
237
251
|
const train = 'first make the release train usable: '; // the train row names the same step
|
|
238
|
-
|
|
252
|
+
const fix = c.fix.startsWith(train) ? c.fix.slice(train.length) : c.fix;
|
|
253
|
+
// Every setup a fix names (alone, after "quit X, then run", or with --with) becomes the step's own
|
|
254
|
+
// command; a fix that already names a train is left as written.
|
|
255
|
+
push(fix.includes('--train') ? fix : fix.split(`${D.NPX} setup`).join(setupStep));
|
|
239
256
|
}
|
|
240
257
|
for (const i of items.filter((x) => x.kind === 'install' && !x.selected)) {
|
|
241
258
|
const pr = catalog.byId(i.product);
|
|
@@ -245,8 +262,7 @@ async function setup({
|
|
|
245
262
|
if (result.actions.some((a) => a.kind === 'update' && a.outcome === 'done' && /[1-9]\d* change/.test(a.detail)) || installed.length) {
|
|
246
263
|
push('Restart your coding agents: skills and MCP servers load when a session starts.');
|
|
247
264
|
}
|
|
248
|
-
|
|
249
|
-
return finish(result, home, after);
|
|
265
|
+
return steps;
|
|
250
266
|
}
|
|
251
267
|
|
|
252
268
|
function finish(result, home, checks) {
|
|
@@ -258,6 +274,8 @@ function finish(result, home, checks) {
|
|
|
258
274
|
return result;
|
|
259
275
|
}
|
|
260
276
|
|
|
277
|
+
const DECLINED = 'You declined every offer; nothing was changed. The checks below still stand.';
|
|
278
|
+
|
|
261
279
|
function render(result, { repairOnly = false } = {}) {
|
|
262
280
|
const lines = [];
|
|
263
281
|
if (result.keyOverride) lines.push(`NOTE: releases are checked against the key in PASSIONCODE_RELEASE_KEY (${result.keyOverride}), not the bundled PassionCode.ai release key.`, '');
|
|
@@ -265,12 +283,12 @@ function render(result, { repairOnly = false } = {}) {
|
|
|
265
283
|
lines.push(`${repairOnly ? 'doctor --fix' : 'setup'} · ${result.mode === 'new' ? 'a new setup' : 'an existing setup'} · ${result.platform}`);
|
|
266
284
|
const todo = result.plan.filter((i) => i.selected);
|
|
267
285
|
if (result.planOnly) {
|
|
268
|
-
lines.push('', todo.length ? 'Plan (nothing was changed):' : 'Nothing to do.');
|
|
286
|
+
lines.push('', todo.length ? 'Plan (nothing was changed):' : result.declined ? DECLINED : 'Nothing to do.');
|
|
269
287
|
for (const i of result.plan) lines.push(` ${i.selected ? '•' : '–'} ${i.detail}${i.note ? ` (${i.note})` : ''}`);
|
|
270
|
-
if (result.trainNotSaved) lines.push('', `The release train (${result.trainNotSaved}) was not saved: run it with --yes, or answer in a terminal
|
|
288
|
+
if (result.trainNotSaved) lines.push('', `The release train (${result.trainNotSaved}) was not saved${result.declined ? '.' : ': run it with --yes, or answer in a terminal.'}`);
|
|
271
289
|
if (todo.length) lines.push('', 'Run it with --yes to apply, or in a terminal to answer one question per app.');
|
|
272
290
|
} else if (!result.actions.length) {
|
|
273
|
-
lines.push('', 'Everything this command can set up is in place; nothing was changed.');
|
|
291
|
+
lines.push('', result.declined ? DECLINED : 'Everything this command can set up is in place; nothing was changed.');
|
|
274
292
|
} else {
|
|
275
293
|
lines.push('', 'Done:');
|
|
276
294
|
for (const x of result.actions) lines.push(` ${x.outcome === 'failed' ? 'FAILED' : 'done '} ${x.detail}${x.error ? `\n ${x.error}` : ''}`);
|
|
@@ -295,7 +313,7 @@ function render(result, { repairOnly = false } = {}) {
|
|
|
295
313
|
for (const c of left) lines.push(` ${c.state === 'fail' ? 'FAIL' : 'warn'} ${c.detail}`);
|
|
296
314
|
}
|
|
297
315
|
if (result.humanSteps.length) {
|
|
298
|
-
lines.push('', 'Your steps (
|
|
316
|
+
lines.push('', 'Your steps (sign-ins, consents and secrets in hidden prompts need you in person):');
|
|
299
317
|
result.humanSteps.forEach((t, n) => lines.push(` ${n + 1}. ${t}`));
|
|
300
318
|
}
|
|
301
319
|
lines.push('', single ? `${a.fail ? `${a.fail} problem(s)` : 'No problems'}. Check again any time: npx @passioncode-ai/passioncode@latest doctor`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/passioncode",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Set up PassionCode.ai on a computer with one command
|
|
3
|
+
"version": "0.2.53",
|
|
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. Check and repair it with the same command or `doctor`.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"passioncode": "bin/passioncode.js"
|
|
7
7
|
},
|
|
@@ -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.53",
|
|
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.53",
|
|
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.53",
|
|
66
66
|
"commit": null,
|
|
67
|
-
"version": "0.2.
|
|
67
|
+
"version": "0.2.53",
|
|
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:cc227b983b8e104b34579a4a12749e15bbd5f35ea30fe75b86475afde618492f",
|
|
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.53",
|
|
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",
|
|
@@ -157,9 +157,9 @@ function decide(state, trust, now = Date.now()) {
|
|
|
157
157
|
const untrusted = [...maintainers, ...(state.publisher ? [state.publisher] : [])].filter((m) => !trusted.has(m));
|
|
158
158
|
if (!maintainers.length || !maintainers.every((m) => typeof m === 'string' && accountName(m) === m)
|
|
159
159
|
|| typeof state.publisher !== 'string' || !state.publisher || accountName(state.publisher) !== state.publisher) {
|
|
160
|
-
lines.push(`[passioncode] ${PACKAGE}@${latest} is on npm but who published it could not be read
|
|
160
|
+
lines.push(`[passioncode] ${PACKAGE}@${latest} is on npm but who published it could not be read, so it is not installed; see SECURITY.md.`);
|
|
161
161
|
} else if (untrusted.length) {
|
|
162
|
-
lines.push(`[passioncode] ${PACKAGE}@${latest} is on npm but published by ${[...new Set(untrusted)].join(', ')}, not a trusted PassionCode publisher
|
|
162
|
+
lines.push(`[passioncode] ${PACKAGE}@${latest} is on npm but published by ${[...new Set(untrusted)].join(', ')}, not a trusted PassionCode publisher, so it is not installed; see SECURITY.md.`);
|
|
163
163
|
} else {
|
|
164
164
|
const auto = (state.config && state.config.auto) !== false;
|
|
165
165
|
const runningAge = now - Date.parse(state.updatingSince);
|
|
@@ -167,7 +167,7 @@ function decide(state, trust, now = Date.now()) {
|
|
|
167
167
|
if (auto && !running) {
|
|
168
168
|
spawn = ['--yes', `${PACKAGE}@${latest}`, 'update', '--quiet'];
|
|
169
169
|
stateChanges.updatingSince = new Date(now).toISOString();
|
|
170
|
-
lines.push(`[passioncode] ${latest} is out (you have ${state.installed}); updating in the background
|
|
170
|
+
lines.push(`[passioncode] ${latest} is out (you have ${state.installed}); updating in the background; it takes effect next session.`);
|
|
171
171
|
} else if (!auto) {
|
|
172
172
|
lines.push(`[passioncode] ${latest} is out (you have ${state.installed}): npx ${PACKAGE}@${latest} update`);
|
|
173
173
|
}
|