dsh-plugin-wiki-tools 0.10.0 → 0.10.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.
Files changed (2) hide show
  1. package/lib/vault.js +29 -1
  2. package/package.json +1 -1
package/lib/vault.js CHANGED
@@ -13,6 +13,7 @@
13
13
 
14
14
  import { createHash } from 'node:crypto'
15
15
  import { spawnSync } from 'node:child_process'
16
+ import { appendFileSync, readFileSync } from 'node:fs'
16
17
  import { mkdir, open, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'
17
18
  import { basename, dirname, isAbsolute, join, relative, sep } from 'node:path'
18
19
  import { parse as parseYaml, stringify as stringifyYaml } from 'yaml'
@@ -227,6 +228,7 @@ export class Vault {
227
228
  gitCommit(message) {
228
229
  if (!this.gitAutoCommit) return
229
230
  const run = args => spawnSync('git', ['-C', this.root, ...args], { encoding: 'utf8' })
231
+ this.ignoreLockFiles()
230
232
  const add = run(['add', '-A'])
231
233
  if (add.status !== 0) throw new Error(`wiki-tools: git add failed in the vault: ${String(add.stderr).trim()}`)
232
234
  const pending = run(['diff', '--cached', '--quiet'])
@@ -236,6 +238,27 @@ export class Vault {
236
238
  }
237
239
  }
238
240
 
241
+ /**
242
+ * Keep advisory lock files out of vault history: cross-process locks under
243
+ * `.vault-meta/locks/` are pure runtime coordination, never vault state.
244
+ * Idempotent; creates or appends the vault's `.gitignore` as needed.
245
+ * @returns {void}
246
+ */
247
+ ignoreLockFiles() {
248
+ const marker = '.vault-meta/locks/'
249
+ const gitignore = join(this.root, '.gitignore')
250
+ let current = ''
251
+ try {
252
+ current = readFileSync(gitignore, 'utf8')
253
+ } catch (error) {
254
+ if (error.code !== 'ENOENT') throw error
255
+ }
256
+ if (!current.split('\n').some(line => line.trim() === marker)) {
257
+ const prefix = current.length === 0 || current.endsWith('\n') ? '' : '\n'
258
+ appendFileSync(gitignore, `${prefix}# wiki-tools runtime locks\n${marker}\n`, 'utf8')
259
+ }
260
+ }
261
+
239
262
  /**
240
263
  * Write one wiki page with complete bookkeeping: frontmatter completion,
241
264
  * filename-uniqueness guard, master-index entry, folder `_index.md` entry,
@@ -354,7 +377,12 @@ export class Vault {
354
377
  if (page.name === title || page.name.toLowerCase() === 'log' || /^lint-report-/.test(page.name)) continue
355
378
  const raw = await readFile(page.path, 'utf8').catch(() => undefined)
356
379
  if (raw === undefined) continue
357
- const pattern = new RegExp(`\\[\\[${escapeRegExp(title)}(\]\]|\||#)`, 'g')
380
+ // Exact-target boundary: the title must end the link target (`]]`),
381
+ // start an alias (`|`), or start an anchor (`#`). Escapes are doubled
382
+ // because this is a string-built RegExp, not a regex literal: single
383
+ // `\]` / `\|` would be eaten by the template literal and leave an
384
+ // empty alternation branch matching every `[[title` prefix.
385
+ const pattern = new RegExp(`\\[\\[${escapeRegExp(title)}(\\]\\]|\\||#)`, 'g')
358
386
  const updated = raw.replace(pattern, `[[${cleanNew}$1`)
359
387
  if (updated !== raw) {
360
388
  await writeFile(page.path, updated, 'utf8')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-wiki-tools",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Native DeepSeek Harness tools for an Obsidian wiki vault: wiki_query, wiki_write, and wiki_lint implement the mechanical core (path routing, delta tracking, index/log bookkeeping, health checks) of the wiki skill suite.",
5
5
  "license": "MIT",
6
6
  "type": "module",