wood-fired-tasks 2.1.0 → 2.1.1

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
@@ -13,6 +13,21 @@ vulnerabilities, supply-chain pinning) are always called out under `Security`.
13
13
 
14
14
  _No changes yet._
15
15
 
16
+ ## [v2.1.1] - 2026-06-09
17
+
18
+ ### Fixed
19
+ - **`tasks self-update` now re-syncs bundled skills/agents into `~/.claude`**
20
+ (PR #57, task #934). The command previously only ran
21
+ `npm i -g wood-fired-tasks@latest`, so a release that added or changed a
22
+ skill (first hit: v2.1.0's `/tasks:set-models`) left self-updaters with
23
+ stale `~/.claude/commands/tasks/` while reporting success — violating the
24
+ README's "keep it up to date" contract. After a clean install, self-update
25
+ now runs the same idempotent `copySkills()`/`copyAgents()` sync `tasks
26
+ setup` uses, reports what it refreshed, and exits non-zero with a
27
+ `tasks setup` remediation hint if the sync itself fails. A contract test
28
+ pins the default sync to setup's own implementation so the update and
29
+ onboarding paths cannot drift.
30
+
16
31
  ## [v2.1.0] - 2026-06-09
17
32
 
18
33
  ### Added
@@ -814,7 +829,9 @@ and the task/project/dependency/comment/subtask domain model.
814
829
  - Task hierarchy (subtasks), dependency service, comments, time estimates
815
830
  (phase 06).
816
831
 
817
- [Unreleased]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v2.0.0...HEAD
832
+ [Unreleased]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v2.1.1...HEAD
833
+ [v2.1.1]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v2.1.0...v2.1.1
834
+ [v2.1.0]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v2.0.6...v2.1.0
818
835
  [v2.0.0]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v1.18.2...v2.0.0
819
836
  [v1.15]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v1.14...v1.15
820
837
  [v1.14]: https://github.com/Wood-Fired-Games/wood-fired-tasks/compare/v1.13...v1.14
package/README.md CHANGED
@@ -143,7 +143,7 @@ user scope.
143
143
 
144
144
  ```bash
145
145
  wood-fired-tasks service install # Linux: user-scoped systemd unit (admin-free)
146
- wood-fired-tasks self-update # npm i -g wood-fired-tasks@latest (no sudo)
146
+ wood-fired-tasks self-update # npm i -g @latest + re-sync skills (no sudo)
147
147
  ```
148
148
 
149
149
  **Point at a shared remote server** (the *Remote client* mode above) with
package/SECURITY.md CHANGED
@@ -14,11 +14,11 @@ security updates. Older tags are provided as-is.
14
14
  | Version | Supported |
15
15
  | ----------------- | ------------------ |
16
16
  | `main` (HEAD) | :white_check_mark: |
17
- | `v2.1.0` (latest) | :white_check_mark: |
17
+ | `v2.1.1` (latest) | :white_check_mark: |
18
18
  | `v1.0` – `v2.0.6` | :x: |
19
19
 
20
20
  "Latest" tracks whichever tag is most recent on GitHub; at the time of
21
- writing that is `v2.1.0`. If you are reading this on an older checkout,
21
+ writing that is `v2.1.1`. If you are reading this on an older checkout,
22
22
  verify the current latest release via
23
23
  `git tag --sort=-creatordate | head -1` or the GitHub Releases page.
24
24
 
@@ -1,12 +1,20 @@
1
1
  import { Command } from 'commander';
2
2
  import { type ChildProcess, type SpawnOptions } from 'child_process';
3
+ import { type CopySkillsResult, type CopyAgentsResult } from './setup.js';
3
4
  /**
4
5
  * `tasks self-update` — frictionless self-update for npm-global installs
5
6
  * (project #36, task #739).
6
7
  *
7
- * Spawns `npm i -g wood-fired-tasks@latest` and exits with that child's exit
8
- * code. The DB schema does NOT need touching here — migrate-on-next-serve
9
- * handles it the next time the service boots against the upgraded binary.
8
+ * Spawns `npm i -g wood-fired-tasks@latest`, then re-syncs the bundled
9
+ * skills/agents into ~/.claude (task #934): the npm install replaces the
10
+ * files under the global prefix in place, so the post-install copySkills /
11
+ * copyAgents read the NEW version's assets even though this process is still
12
+ * running the old binary. Without this step, any release that adds or
13
+ * changes a skill leaves self-updaters with stale ~/.claude/commands/tasks
14
+ * while self-update reports success — violating the README's "keep it up to
15
+ * date" contract. The DB schema does NOT need touching here —
16
+ * migrate-on-next-serve handles it the next time the service boots against
17
+ * the upgraded binary.
10
18
  *
11
19
  * EACCES policy: a global npm install under a root-owned prefix fails with
12
20
  * EACCES. We DO NOT escalate (no sudo / runas / elevation of ANY kind).
@@ -17,9 +25,14 @@ import { type ChildProcess, type SpawnOptions } from 'child_process';
17
25
  */
18
26
  export type SpawnFn = (command: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
19
27
  export type NotifyFn = (currentVersion: string) => void | Promise<void>;
28
+ export type SyncAssetsFn = () => {
29
+ skills: CopySkillsResult;
30
+ agents: CopyAgentsResult;
31
+ };
20
32
  export interface SelfUpdateDeps {
21
33
  spawn?: SpawnFn;
22
34
  notify?: NotifyFn;
35
+ syncAssets?: SyncAssetsFn;
23
36
  }
24
37
  /**
25
38
  * True when a spawn error / non-zero exit looks like an EACCES-class
@@ -3,6 +3,7 @@ import { spawn as nodeSpawn } from 'child_process';
3
3
  import { colorError, colorInfo, colorSuccess, colorWarn } from '../output/formatters.js';
4
4
  import { VERSION } from '../../utils/version.js';
5
5
  import { buildNpmInvocation } from '../util/npm-spawn.js';
6
+ import { copySkills, copyAgents } from './setup.js';
6
7
  const PACKAGE_NAME = 'wood-fired-tasks';
7
8
  /**
8
9
  * True when a spawn error / non-zero exit looks like an EACCES-class
@@ -98,6 +99,7 @@ export const selfUpdateCommand = new Command('self-update')
98
99
  const deps = selfUpdateCommand._deps ?? {};
99
100
  const spawn = deps.spawn ?? nodeSpawn;
100
101
  const notify = deps.notify ?? defaultNotify;
102
+ const syncAssets = deps.syncAssets ?? (() => ({ skills: copySkills(), agents: copyAgents() }));
101
103
  // update-notifier nudge: surface a "newer version available" hint before
102
104
  // we attempt the upgrade. Best-effort and never blocks the update.
103
105
  await notify(VERSION);
@@ -119,6 +121,25 @@ export const selfUpdateCommand = new Command('self-update')
119
121
  process.exitCode = code ?? 1;
120
122
  return;
121
123
  }
124
+ // npm replaced the package files under the global prefix in place, so the
125
+ // sync below reads the NEW version's dist/skills even though this process
126
+ // still runs the old binary. A sync failure is loud and non-zero: "update
127
+ // succeeded but your skills are stale" is exactly the silent state this
128
+ // step exists to eliminate (task #934).
129
+ try {
130
+ const { skills, agents } = syncAssets();
131
+ const refreshed = skills.written.length + agents.written.length;
132
+ console.log(refreshed > 0
133
+ ? colorInfo(`Refreshed ${skills.written.length} skill(s) in ${skills.destDir} and ${agents.written.length} agent(s) in ${agents.destDir}`)
134
+ : colorInfo(`Skills and agents already up to date in ${skills.destDir}`));
135
+ }
136
+ catch (syncError) {
137
+ const message = syncError instanceof Error ? syncError.message : String(syncError);
138
+ console.error(colorError(`Update installed, but syncing bundled skills/agents into ~/.claude failed: ${message}`));
139
+ console.error(colorWarn(`Run \`${PACKAGE_NAME} setup\` to retry the skills sync.`));
140
+ process.exitCode = 1;
141
+ return;
142
+ }
122
143
  console.log(colorSuccess(`Updated ${PACKAGE_NAME}. The schema migrates automatically on next serve.`));
123
144
  process.exitCode = 0;
124
145
  });
package/docs/SETUP.md CHANGED
@@ -158,8 +158,13 @@ unless `--port` overrides it. The unauthenticated `GET /health` route returns
158
158
  wood-fired-tasks self-update
159
159
  ```
160
160
 
161
- This runs `npm i -g wood-fired-tasks@latest` and exits with npm's exit code. It
162
- **never escalates**: on an EACCES (root-owned global prefix) it prints the
161
+ This runs `npm i -g wood-fired-tasks@latest`, then re-syncs the bundled
162
+ skills into `~/.claude/commands/tasks/` and the subagent definitions into
163
+ `~/.claude/agents/` — the same idempotent copy `setup` performs, so a release
164
+ that adds or changes a skill is fully picked up by `self-update` alone (no
165
+ `setup` re-run needed). If the install succeeds but the skills sync fails, it
166
+ says so and exits non-zero; re-run `wood-fired-tasks setup` to retry the sync.
167
+ It **never escalates**: on an EACCES (root-owned global prefix) it prints the
163
168
  writable-prefix remediation (the same `~/.npm-global` fix as `--fix-npm-prefix`)
164
169
  and exits non-zero rather than suggesting sudo. The database schema needs no
165
170
  special handling — it migrates automatically the next time `serve` (or the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wood-fired-tasks",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Network-wide task tracking system for Wood Fired Games",
5
5
  "keywords": [
6
6
  "task-tracker",