@dboio/cli 0.15.1 → 0.15.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dboio/cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "CLI for the DBO.io framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbo",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "DBO.io CLI integration for Claude Code",
5
5
  "author": {
6
6
  "name": "DBO.io"
@@ -22,16 +22,6 @@ import { checkToeStepping } from '../lib/toe-stepping.js';
22
22
  import { runPendingMigrations } from '../lib/migrations.js';
23
23
  // AUTO-ADD DISABLED: import { findUnaddedFiles, detectBinFile, submitAdd } from './add.js';
24
24
 
25
- function _getMetaCompanionPaths(meta, metaPath) {
26
- const dir = dirname(metaPath);
27
- const paths = [];
28
- for (const col of (meta._contentColumns || [])) {
29
- const ref = meta[col];
30
- if (ref && String(ref).startsWith('@')) paths.push(join(dir, String(ref).substring(1)));
31
- }
32
- return paths;
33
- }
34
-
35
25
  /**
36
26
  * Resolve an @reference file path to an absolute filesystem path.
37
27
  * "@filename.ext" → relative to the metadata file's directory (existing behaviour)
@@ -850,11 +840,9 @@ async function pushDirectory(dirPath, client, options, modifyKey = null, transac
850
840
  await updateBaselineAfterPush(baseline, successfulPushes);
851
841
  }
852
842
 
853
- // Re-tag successfully pushed files as Synced (best-effort)
854
- for (const { meta, metaPath } of successfulPushes) {
855
- for (const filePath of _getMetaCompanionPaths(meta, metaPath)) {
856
- setFileTag(filePath, 'synced').catch(() => {});
857
- }
843
+ // Re-tag successfully pushed metadata files as Synced (best-effort)
844
+ for (const { metaPath } of successfulPushes) {
845
+ setFileTag(metaPath, 'synced').catch(() => {});
858
846
  }
859
847
 
860
848
  log.info(`Push complete: ${succeeded} succeeded, ${failed} failed, ${skipped} skipped`);
@@ -80,12 +80,15 @@ export async function tagProjectFiles(options = {}) {
80
80
  const counts = { synced: 0, modified: 0, untracked: 0, conflict: 0, trashed: 0 };
81
81
 
82
82
  if (clearAll) {
83
- const companions = (await Promise.all(metaPaths.map(mp => _getCompanionPaths(mp)))).flat();
84
- await _bulkApplyTags(companions.map(fp => ({ filePath: fp, clear: true })));
83
+ // Clear tags from ALL files in the project: metadata, companions, and any
84
+ // legacy-tagged content files (from old untracked detection).
85
+ const contentFiles = await _collectContentFiles(dir, ig);
86
+ const allFiles = [...metaPaths, ...contentFiles];
87
+ await _bulkApplyTags(allFiles.map(fp => ({ filePath: fp, clear: true })));
85
88
  return null;
86
89
  }
87
-
88
- // Collect file→status pairs from metadata
90
+ // Tag metadata files — the source of truth for sync status.
91
+ // Companion files are dependent artifacts and should not carry their own tags.
89
92
  const toTag = [];
90
93
  for (const metaPath of metaPaths) {
91
94
  const inTrash = metaPath.replace(/\\/g, '/').includes('/trash/');
@@ -93,20 +96,9 @@ export async function tagProjectFiles(options = {}) {
93
96
  ? 'trashed'
94
97
  : (await hasLocalModifications(metaPath, config).catch(() => false)) ? 'modified'
95
98
  : 'synced';
96
- const companions = await _getCompanionPaths(metaPath);
97
- for (const filePath of companions) {
98
- toTag.push({ filePath, status });
99
- counts[status]++;
100
- if (verbose) console.log(` ${status.padEnd(10)} ${relative(dir, filePath)}`);
101
- }
102
- }
103
-
104
- // Detect untracked files (content files without any metadata)
105
- const untrackedFiles = await _findUntrackedFiles(dir, ig, metaPaths);
106
- for (const filePath of untrackedFiles) {
107
- toTag.push({ filePath, status: 'untracked' });
108
- counts.untracked++;
109
- if (verbose) console.log(` untracked ${relative(dir, filePath)}`);
99
+ toTag.push({ filePath: metaPath, status });
100
+ counts[status]++;
101
+ if (verbose) console.log(` ${status.padEnd(10)} ${relative(dir, metaPath)}`);
110
102
  }
111
103
 
112
104
  await _bulkApplyTags(toTag);
@@ -132,6 +124,11 @@ async function _getCompanionPaths(metaPath) {
132
124
  try { await stat(candidate); paths.push(candidate); } catch { /* missing */ }
133
125
  }
134
126
  }
127
+ // Check _mediaFile (single media companion reference)
128
+ if (meta._mediaFile && String(meta._mediaFile).startsWith("@")) {
129
+ const candidate = join(dir, String(meta._mediaFile).substring(1));
130
+ try { await stat(candidate); paths.push(candidate); } catch { /* missing */ }
131
+ }
135
132
  for (const col of (meta._mediaColumns || [])) {
136
133
  const ref = meta[col];
137
134
  if (ref && String(ref).startsWith('@')) {