prjct-cli 3.13.0 → 3.14.0

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
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [3.14.0] - 2026-07-01
6
+
7
+ ### Features
8
+
9
+ - triage drives orchestration — trivial→direct, complex→SDD+TDD+crew, per-subagent model (#499)
10
+
11
+ ### Performance
12
+
13
+ - run bundled entry in-process — 41% faster commands (#498)
14
+
15
+
5
16
  ## [3.13.0] - 2026-07-01
6
17
 
7
18
  ### Features
package/bin/prjct.cjs CHANGED
@@ -12,6 +12,7 @@ const childProcess = require('node:child_process')
12
12
  const fs = require('node:fs')
13
13
  const os = require('node:os')
14
14
  const path = require('node:path')
15
+ const url = require('node:url')
15
16
 
16
17
  const SCRIPT_PATH = fs.realpathSync(__filename)
17
18
  const SCRIPT_DIR = path.dirname(SCRIPT_PATH)
@@ -280,6 +281,47 @@ function runWithNode(args) {
280
281
  spawnAndExit(process.execPath, [distBin, ...args], { env: withSqliteFlag() })
281
282
  }
282
283
 
284
+ /**
285
+ * Fastest path: run the bundled entry IN-PROCESS under the node that already
286
+ * booted to run this launcher — NO second runtime boot. The historical design
287
+ * spawned a fresh bun/node process solely to inject `--experimental-sqlite`;
288
+ * but node:sqlite is available WITHOUT that flag on node >=22.5 (the supported
289
+ * minimum), so the second process is pure overhead (~40ms). The bundled
290
+ * `dist/bin/prjct.mjs` is a thin cold-entry (daemon client) that reads
291
+ * process.argv directly — identical argv in-process vs spawned — and calls
292
+ * process.exit() itself, so once imported it OWNS the process.
293
+ *
294
+ * Returns true once the entry has started (caller must NOT fall through to a
295
+ * spawn, or the command would run twice). Returns false only when in-process
296
+ * load is not viable (old node, missing bundle, Windows) or the module fails
297
+ * to load — then the caller falls back to the spawn path.
298
+ */
299
+ async function runInProcess() {
300
+ // Windows keeps the well-tested spawn path (shim/pathext nuances).
301
+ if (process.platform === 'win32') return false
302
+ const distBin = path.join(ROOT_DIR, 'dist', 'bin', 'prjct.mjs')
303
+ if (!fs.existsSync(distBin) || !nodeVersionOk()) return false
304
+ // node:sqlite is experimental on node 22.x → suppress the cosmetic
305
+ // ExperimentalWarning so stderr stays clean for `--md` consumers (the
306
+ // module is functionally available without the flag).
307
+ const origEmit = process.emitWarning.bind(process)
308
+ process.emitWarning = (warning, ...rest) => {
309
+ const msg = typeof warning === 'string' ? warning : warning?.message || ''
310
+ if (typeof msg === 'string' && /sqlite/i.test(msg)) return
311
+ return origEmit(warning, ...rest)
312
+ }
313
+ try {
314
+ // Resolves when the entry's top-level finishes; the entry keeps the event
315
+ // loop alive (daemon socket / core fallback) and exits the process itself.
316
+ await import(url.pathToFileURL(distBin).href)
317
+ return true
318
+ } catch {
319
+ // Module failed to load in-process — restore warnings and fall back.
320
+ process.emitWarning = origEmit
321
+ return false
322
+ }
323
+ }
324
+
283
325
  function runWithBun(args) {
284
326
  if (process.platform === 'win32') return false
285
327
  const distBin = path.join(ROOT_DIR, 'dist', 'bin', 'prjct.mjs')
@@ -289,7 +331,7 @@ function runWithBun(args) {
289
331
  return true
290
332
  }
291
333
 
292
- function main() {
334
+ async function main() {
293
335
  const args = process.argv.slice(2)
294
336
  if (args[0] === 'mcp-server') runMcpServer(args)
295
337
 
@@ -311,8 +353,14 @@ function main() {
311
353
  writeSetupStamp(version)
312
354
  }
313
355
 
356
+ // Fastest first: run the entry in-process under this node (no second boot).
357
+ // Only falls through to a spawned runtime if in-process load isn't viable.
358
+ if (await runInProcess()) return
314
359
  if (runWithBun(args)) return
315
360
  runWithNode(args)
316
361
  }
317
362
 
318
- main()
363
+ main().catch((error) => {
364
+ console.error(`Error: ${error?.message || error}`)
365
+ process.exit(1)
366
+ })