@sabaiway/agent-workflow-kit 1.8.0 → 1.8.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
@@ -4,6 +4,37 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
4
4
  is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
5
5
  every `migrations/<version>-<slug>.md` newer than it, in semver order.
6
6
 
7
+ ## 1.8.1 — Fix: `npx … init` ran nothing (the installer's own run-guard mis-fired under npx)
8
+
9
+ 1.8.0 set out to fix "`npx <pkg> init` quietly did nothing" — and shipped a *second*, unrelated
10
+ silent no-op in the same spot. The reported symptom: `npx @sabaiway/agent-workflow-kit@latest init`
11
+ installs the package, prints the npx "Ok to proceed?" line, and then **prints nothing and does
12
+ nothing** — none of 1.8.0's new DX messaging, no install, exit 0.
13
+
14
+ Root cause: the bottom-of-file run-guard that gates `main()` so importing the module has no side
15
+ effects:
16
+
17
+ ```js
18
+ const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
19
+ ```
20
+
21
+ npx never runs `bin/install.mjs` by its real path — it runs the `node_modules/.bin/agent-workflow-kit`
22
+ **symlink** to it. Node resolves `import.meta.url` to the real file but leaves `process.argv[1]` as the
23
+ symlink path, so the string compare is always false, `main()` never runs, and the process exits 0
24
+ without a word. (Running `node bin/install.mjs` directly — as the test suite did — has no symlink, which
25
+ is why every test passed while real `npx` was broken.)
26
+
27
+ - **Fix:** the guard now compares **real paths** (`realpathSync` on both sides), which collapses the
28
+ `.bin` symlink so direct and npx invocations both register as a direct run; it also holds under
29
+ `--preserve-symlinks`. Import-with-no-`argv[1]` and a missing file still fall through to `false`, so
30
+ importing the module continues to run nothing.
31
+ - **Regression test:** a new case invokes the installer **through a symlink** (the exact `.bin` shim
32
+ npx uses) and asserts it both prints and writes the payload — the previous suite never exercised a
33
+ symlinked invocation, so the bug slipped through.
34
+
35
+ Installer bugfix only — no `docs/ai` structural change, deployment-lineage head stays **`1.3.0`**, no
36
+ migration.
37
+
7
38
  ## 1.8.0 — Stale-version DX: `@latest` everywhere + a no-network never-downgrade gate
8
39
 
9
40
  A returning user ran the headline `npx @sabaiway/agent-workflow-kit init` and it quietly did nothing:
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.8.0'
6
+ version: '1.8.1'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
package/bin/install.mjs CHANGED
@@ -23,9 +23,9 @@
23
23
  // Dependency-free, Node >= 18.
24
24
 
25
25
  import { readFile, mkdir } from 'node:fs/promises';
26
- import { existsSync, lstatSync } from 'node:fs';
26
+ import { existsSync, lstatSync, realpathSync } from 'node:fs';
27
27
  import { dirname, resolve } from 'node:path';
28
- import { fileURLToPath, pathToFileURL } from 'node:url';
28
+ import { fileURLToPath } from 'node:url';
29
29
  import { homedir } from 'node:os';
30
30
  import { spawnSync } from 'node:child_process';
31
31
  import { copyTreeRefresh } from '../tools/fs-safe.mjs';
@@ -274,7 +274,22 @@ To update the kit later, re-run: npx @sabaiway/agent-workflow-kit@latest init`)
274
274
 
275
275
  // Run main() only when executed directly (npx / node bin/install.mjs), never on import — so tests
276
276
  // can import this module to assert it has no side effects. Same idiom as tools/detect-backends.mjs.
277
- const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
277
+ //
278
+ // Compare by REAL path, not by URL string: npx invokes the bin through a symlink in node_modules/.bin,
279
+ // so process.argv[1] is that symlink while import.meta.url is the resolved real file — a raw string
280
+ // compare reads them as different, main() never runs, and `npx … init` exits silently (the reported
281
+ // "nothing happens after install" bug). realpathSync collapses the symlink so both sides match; it also
282
+ // holds under --preserve-symlinks. A bare `node -e` (no argv[1]) and a missing file (realpath throws)
283
+ // both correctly fall through to false — importing the module still runs nothing.
284
+ const isDirectRun = (() => {
285
+ const invoked = process.argv[1];
286
+ if (!invoked) return false;
287
+ try {
288
+ return realpathSync(invoked) === realpathSync(fileURLToPath(import.meta.url));
289
+ } catch {
290
+ return false;
291
+ }
292
+ })();
278
293
  if (isDirectRun) {
279
294
  main().catch((err) => {
280
295
  console.error(err);
@@ -78,6 +78,31 @@ describe('kit installer — payload + symlink-traversal hardening', () => {
78
78
  });
79
79
  });
80
80
 
81
+ describe('kit installer — runs through the npx bin symlink', () => {
82
+ let dir;
83
+ beforeEach(async () => {
84
+ dir = await mkdtemp(join(tmpdir(), 'aw-kit-symlink-'));
85
+ });
86
+ afterEach(async () => {
87
+ await rm(dir, { recursive: true, force: true });
88
+ });
89
+
90
+ it('main() runs when invoked through a symlink (the node_modules/.bin shim npx uses)', async () => {
91
+ // npx never runs bin/install.mjs by its real path — it runs node_modules/.bin/agent-workflow-kit,
92
+ // a symlink to it. Node resolves import.meta.url to the REAL file but leaves argv[1] as the symlink,
93
+ // so a string compare of the two makes isDirectRun false and main() silently no-ops. Reproduce that
94
+ // exact invocation: run the installer via a symlink and assert it actually installed (visible output
95
+ // + payload on disk). A regression here means `npx … init` goes quiet again.
96
+ const shim = join(dir, 'agent-workflow-kit'); // stands in for node_modules/.bin/<name>
97
+ await symlink(INSTALLER, shim);
98
+ const target = join(dir, 'home', 'agent-workflow-kit');
99
+ const res = spawnSync(process.execPath, [shim, '--dir', target, '--no-launchers'], { encoding: 'utf8' });
100
+ assert.equal(res.status, 0, res.stderr);
101
+ assert.match(res.stdout, /installed v|updated the kit/);
102
+ assert.ok(existsSync(join(target, 'SKILL.md')), 'install through the symlink must write the payload');
103
+ });
104
+ });
105
+
81
106
  describe('kit installer — module hygiene', () => {
82
107
  it('importing install.mjs runs nothing (main() is guarded by isDirectRun)', () => {
83
108
  // `node -e` has no argv[1], so isDirectRun is false → importing must not run main()
package/capability.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "agent-workflow-kit",
5
5
  "kind": "composition-root",
6
- "version": "1.8.0",
6
+ "version": "1.8.1",
7
7
  "provides": [],
8
8
  "roles": {},
9
9
  "detect": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sabaiway/agent-workflow-kit",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Portable, cross-agent memory & workflow for AI coding agents — Claude Code, Codex, Cursor, Devin Desktop. One command deploys an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement into any repo.",
5
5
  "keywords": [
6
6
  "ai-agents",