@passioncode-ai/passioncode 0.2.51 → 0.2.52

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,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.52 - 2026-11-02
4
+
5
+ ### Fixed
6
+
7
+ - `setup` in a terminal, answered "no" to every offer (at least one of them defaulting to yes) and so
8
+ changing nothing, says "You declined every offer; nothing was changed." instead of "Everything this
9
+ 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
10
+ advice to answer in a terminal (PC-91). Forgetting a train with `--train none` is still a change.
11
+ Such a run now lists `setup` among the person's steps when a failing or warning check's own fix
12
+ names it (`setup --train <name>` when the run declined that train).
13
+
3
14
  ## 0.2.51 - 2026-10-30
4
15
 
5
16
  ### 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
- shown as a plan. The skills are pinned by the launcher release itself (`family.json`). Which
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/lib/setup.js CHANGED
@@ -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 that defaulted
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) { result.planOnly = true; result.trainNotSaved = trainName; return finish(result, home, before); }
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
- // The person's steps, once: every remaining problem's fix, the guides of the apps just installed,
230
- // what an install leaves to a person, and a restart when skills or MCP servers changed.
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
- push(c.fix.startsWith(train) ? c.fix.slice(train.length) : c.fix);
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
- result.humanSteps = steps;
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}` : ''}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@passioncode-ai/passioncode",
3
- "version": "0.2.51",
3
+ "version": "0.2.52",
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.51",
38
+ "version": "0.2.52",
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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "family": "passioncode",
3
- "version": "0.2.51",
3
+ "version": "0.2.52",
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.51",
65
+ "ref": "v0.2.52",
66
66
  "commit": null,
67
- "version": "0.2.51",
67
+ "version": "0.2.52",
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:66330438761bc6a9dfea1f8b6a63751b3db8b23bbe085633739d492832312d0b",
75
+ "contentHash": "sha256:8b9f7952e681760859099cf84a4f29a0cd264dde45b7287765aac937218b068e",
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.51",
5
+ "version": "0.2.52",
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",