fdeops 5.1.17 → 5.1.18

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/bin/fde.js CHANGED
@@ -2574,23 +2574,35 @@ function cmdIngest(args) {
2574
2574
 
2575
2575
  const box = inboxDir(eng)
2576
2576
  try {
2577
- if (!checkedInbox(eng)) fs.mkdirSync(box)
2577
+ if (!checkedInbox(eng)) {
2578
+ try { fs.mkdirSync(box) } catch (error) { if (error.code !== 'EEXIST') throw error }
2579
+ }
2578
2580
  checkedInbox(eng)
2579
2581
  } catch (e) { failFs(e, 'create inbox', box) }
2580
2582
  const compact = new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z')
2581
- const id = `${compact}-${source}-${titleSlug}.md`
2582
- const dest = path.join(box, id)
2583
- const body = [
2584
- '---',
2585
- `source: ${source}`,
2586
- `title: ${title.replace(/\n/g, ' ')}`,
2587
- `staged: ${new Date().toISOString()}`,
2588
- `id: ${id}`,
2589
- '---',
2590
- '',
2591
- input.replace(/\s+$/, '') + '\n',
2592
- ].join('\n')
2593
- withFileLock(dest, () => { atomicWriteFile(dest, body) })
2583
+ const stem = `${compact}-${source}-${titleSlug}`
2584
+ let id, dest
2585
+ // Serialize name selection with the write: two agents can stage in one second.
2586
+ withFileLock(path.join(box, '.stage'), () => {
2587
+ let suffix = 0
2588
+ while (true) {
2589
+ id = `${stem}${suffix ? `-${suffix}` : ''}.md`
2590
+ dest = path.join(box, id)
2591
+ try { fs.lstatSync(dest); suffix++ }
2592
+ catch (error) { if (error.code === 'ENOENT') break; throw error }
2593
+ }
2594
+ const body = [
2595
+ '---',
2596
+ `source: ${source}`,
2597
+ `title: ${title.replace(/\n/g, ' ')}`,
2598
+ `staged: ${new Date().toISOString()}`,
2599
+ `id: ${id}`,
2600
+ '---',
2601
+ '',
2602
+ input.replace(/\s+$/, '') + '\n',
2603
+ ].join('\n')
2604
+ atomicWriteFile(dest, body)
2605
+ })
2594
2606
  console.log(`staged → ${dest}`)
2595
2607
  console.log(`id: ${id}`)
2596
2608
  console.log('next: fde ingest propose ' + id)
@@ -3932,9 +3944,13 @@ function cmdDashboard(args) {
3932
3944
  // Stamped into the vault so a stale folder is identifiable. Best-effort: a
3933
3945
  // missing package.json must not stop an FDE generating their vault.
3934
3946
  function cliVersion() {
3935
- try {
3936
- return String(JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')).version || '')
3937
- } catch (_) { return '' }
3947
+ for (const file of [path.join(__dirname, 'package.json'), path.join(__dirname, '..', 'package.json')]) {
3948
+ try {
3949
+ const metadata = JSON.parse(fs.readFileSync(file, 'utf8'))
3950
+ if (metadata.name === 'fdeops' && typeof metadata.version === 'string') return metadata.version
3951
+ } catch (_) {}
3952
+ }
3953
+ return ''
3938
3954
  }
3939
3955
 
3940
3956
  function valueLedgerRows(eng) {
@@ -4318,7 +4334,7 @@ switch (cmd) {
4318
4334
  case 'setup': finishAsync(setup.command(setupStore, args)); break
4319
4335
  case 'privacy':
4320
4336
  if (args.length) { console.error('usage: fde privacy'); process.exitCode = 2; break }
4321
- console.log(`FDEOps ${require('../package.json').version} - identifier masking enabled by default.\nCLI responses, smart proposals, handoff packets and ingest MCP results use local aliases.\nPatterns: common emails, international/US phones, SSN-shaped identifiers and supported credentials.\nNames and arbitrary sensitive prose are not automatically detected; mark them <private> or supply local custom terms with fde setup.\nRaw files, pasted chat and upstream MCP content bypass this protection. Local reports retain identifiers by default; fde setup can also mask newly generated report content.`)
4337
+ console.log(`FDEOps ${cliVersion() || '(version unavailable)'} - identifier masking enabled by default.\nCLI responses, smart proposals, handoff packets and ingest MCP results use local aliases.\nPatterns: common emails, international/US phones, SSN-shaped identifiers and supported credentials.\nNames and arbitrary sensitive prose are not automatically detected; mark them <private> or supply local custom terms with fde setup.\nRaw files, pasted chat and upstream MCP content bypass this protection. Local reports retain identifiers by default; fde setup can also mask newly generated report content.`)
4322
4338
  break
4323
4339
  case 'demo': cmdDemo(args); break
4324
4340
  case 'scan': cmdScan(); break
package/bin/install.js CHANGED
@@ -22,7 +22,8 @@ const LIB_SRC = path.join(__dirname, 'lib')
22
22
  const GLOBAL_SKILLS_DIR = path.join(os.homedir(), '.claude', 'skills')
23
23
  const GLOBAL_HOOKS_DIR = path.join(os.homedir(), '.claude', 'hooks')
24
24
  const HOOK_SCRIPTS = ['session-start', 'session-stop', 'pre-compact']
25
- const ENGAGEMENTS_ROOT = path.join(os.homedir(), 'fde-engagements')
25
+ const ENGAGEMENTS_ROOT = (process.env.FDEOPS_ENGAGEMENTS_ROOT || '').trim().replace(/^~/, os.homedir())
26
+ || path.join(os.homedir(), 'fde-engagements')
26
27
 
27
28
  function copyDir(src, dest) {
28
29
  checkTree(src, dest)
@@ -268,6 +269,7 @@ function installSkills(opts = {}) {
268
269
  mkdir(cliHome)
269
270
  copyFile(path.join(__dirname, 'fde.js'), path.join(cliHome, 'fde.js'))
270
271
  copyDir(LIB_SRC, path.join(cliHome, 'lib'))
272
+ copyFile(path.join(__dirname, '..', 'package.json'), path.join(cliHome, 'package.json'))
271
273
  try { fs.chmodSync(path.join(cliHome, 'fde.js'), '755') } catch (_) {}
272
274
  copyDir(FDE_TEMPLATES_SRC, path.join(cliHome, 'templates', '.fde'))
273
275
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops-ingest-mcp",
3
- "version": "5.1.17",
3
+ "version": "5.1.18",
4
4
  "private": true,
5
5
  "description": "Thin stdio MCP sink for FDEOps ingest (stage \u2192 propose \u2192 apply). Zero runtime dependencies.",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fdeops",
3
- "version": "5.1.17",
3
+ "version": "5.1.18",
4
4
  "description": "Skills for forward deployed engineers across strategy, architecture and engineering. Use individual tasks or @fde coordination; local customer memory supports continuity.",
5
5
  "bin": {
6
6
  "fdeops": "bin/install.js",
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "fdeops",
4
- "version": "5.1.17",
4
+ "version": "5.1.18",
5
5
  "description": "Skills for forward deployed engineers across strategy, architecture and engineering. Use individual tasks or @fde coordination; local customer memory supports continuity.",
6
6
  "author": {
7
7
  "name": "Subash Natarajan",