@vibecompass/vibecompass 0.6.0 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecompass/vibecompass",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Local-first project-memory core for VibeCompass",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { realpathSync } from 'node:fs';
4
4
  import { pathToFileURL } from 'node:url';
5
- import { connectHostedProjectMemory, initializeProjectMemory } from './init.js';
5
+ import { connectHostedProjectMemory, initializeProjectMemory, setDefaultSyncTarget } from './init.js';
6
6
  import { preflightDocsReview } from './docs-review.js';
7
7
  import { resolveConnectHostedCliOptions, resolveInitCliOptions } from './setup.js';
8
8
  import { closeProjectSession, listProjectSessions, startProjectSession, switchProjectSession } from './session.js';
@@ -140,6 +140,10 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
140
140
  });
141
141
  io.stdout.write(`Connected hosted VibeCompass for ${result.mode}\n`);
142
142
  io.stdout.write(`Updated ${result.projectFilePath}\n`);
143
+ if (result.syncTarget) {
144
+ io.stdout.write(`Sync target: ${result.syncTarget.name} (default: ${result.syncTarget.defaultTarget})\n`);
145
+ io.stdout.write(`Select per command with --sync-target ${result.syncTarget.name}, or switch the default with: vibecompass sync-target ${result.syncTarget.name}\n`);
146
+ }
143
147
  io.stdout.write(`Next step: set ${result.syncEnvVar} locally before your first hosted command.\n`);
144
148
  if (result.mode === 'local-primary') {
145
149
  io.stdout.write('Then run: vibecompass push\n');
@@ -150,6 +154,28 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
150
154
  return 0;
151
155
  }
152
156
 
157
+ if (parsed.command === 'sync-target') {
158
+ const result = await setDefaultSyncTarget({
159
+ ...parsed.options,
160
+ ...(runtime.cwd ? { cwd: runtime.cwd } : {}),
161
+ });
162
+ if (parsed.options.targetName) {
163
+ io.stdout.write(
164
+ result.changed
165
+ ? `Default sync target set to ${result.defaultTarget}\n`
166
+ : `Default sync target already ${result.defaultTarget}\n`,
167
+ );
168
+ io.stdout.write(`Updated ${result.projectFilePath}\n`);
169
+ } else {
170
+ io.stdout.write(`Default sync target: ${result.defaultTarget ?? '(none)'}\n`);
171
+ }
172
+ for (const [name, target] of Object.entries(result.targets)) {
173
+ const marker = name === result.defaultTarget ? '*' : ' ';
174
+ io.stdout.write(`${marker} ${name}: ${target.api_url} (project ${target.project_id}, env ${target.credential_env_var})\n`);
175
+ }
176
+ return 0;
177
+ }
178
+
153
179
  if (parsed.command === 'status') {
154
180
  const result = await getProjectStatus({
155
181
  ...parsed.options,
@@ -260,11 +286,32 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
260
286
  if (result.localReview) {
261
287
  io.stdout.write(`Local review output: ${result.localReview.output_path}\n`);
262
288
  }
289
+ if (result.rebuild) {
290
+ io.stdout.write(`Rebuild scope: ${result.rebuild.scope_path}\n`);
291
+ io.stdout.write(`Stale policy: ${result.rebuild.stale_policy}\n`);
292
+ io.stdout.write(`Architecture docs: ${result.rebuild.architecture_doc_count}\n`);
293
+ for (const entry of result.rebuild.architecture_docs) {
294
+ io.stdout.write(`- ${entry.path} (${entry.action}${entry.archive_path ? ` -> ${entry.archive_path}` : ''})\n`);
295
+ }
296
+ }
263
297
  if (result.applied) {
264
298
  io.stdout.write(`Applied architecture docs: ${result.applied.architecture_docs.length}\n`);
265
299
  for (const entry of result.applied.architecture_docs) {
266
300
  io.stdout.write(`- ${entry.path} (${entry.status})\n`);
267
301
  }
302
+ if (result.applied.coverage) {
303
+ io.stdout.write(`Applied coverage plan: ${result.applied.coverage.area_count} areas`);
304
+ if (typeof result.applied.coverage.coverage_score === 'number') {
305
+ io.stdout.write(` (${Math.round(result.applied.coverage.coverage_score * 100)}% accepted)`);
306
+ }
307
+ io.stdout.write('\n');
308
+ }
309
+ if (Array.isArray(result.applied.decision_candidates) && result.applied.decision_candidates.length > 0) {
310
+ io.stdout.write(`Applied decision recommendations: ${result.applied.decision_candidates.length}\n`);
311
+ for (const entry of result.applied.decision_candidates) {
312
+ io.stdout.write(`- D-${String(entry.decision_id).padStart(3, '0')}: ${entry.title} (${entry.target_path})\n`);
313
+ }
314
+ }
268
315
  }
269
316
  if (result.appliedDecisionArtifact) {
270
317
  io.stdout.write(`Applied decision artifact: ${result.appliedDecisionArtifact.artifact_id}\n`);
@@ -272,7 +319,9 @@ export async function runCli(argv, io = createDefaultIo(), runtime = {}) {
272
319
  io.stdout.write(`Target: ${result.appliedDecisionArtifact.target_path}\n`);
273
320
  }
274
321
  writeWarnings(io, result.warnings);
275
- io.stdout.write(`Recorded ${result.statePath}\n`);
322
+ if (result.recorded !== false) {
323
+ io.stdout.write(`Recorded ${result.statePath}\n`);
324
+ }
276
325
  io.stdout.write(`${result.message}\n`);
277
326
  if (result.reviewPrompt) {
278
327
  io.stdout.write('Architecture review prompt:\n');
@@ -378,6 +427,10 @@ export function parseCliArgs(argv) {
378
427
  return parseConnectHostedArgs(rest);
379
428
  }
380
429
 
430
+ if (command === 'sync-target') {
431
+ return parseSyncTargetArgs(rest);
432
+ }
433
+
381
434
  if (command === 'status') {
382
435
  return parseStatusArgs(rest);
383
436
  }
@@ -679,6 +732,9 @@ function parseConnectHostedArgs(argv) {
679
732
  case '--root':
680
733
  parsed.rootDir = value;
681
734
  break;
735
+ case '--target':
736
+ parsed.targetName = value;
737
+ break;
682
738
  case '--sync-api-url':
683
739
  parsed.syncApiUrl = value;
684
740
  break;
@@ -703,6 +759,7 @@ function parseConnectHostedArgs(argv) {
703
759
  command: 'connect-hosted',
704
760
  options: {
705
761
  rootDir: parsed.rootDir,
762
+ ...(parsed.targetName ? { targetName: parsed.targetName } : {}),
706
763
  ...(syncValues.length > 0
707
764
  ? {
708
765
  sync: {
@@ -1042,6 +1099,21 @@ function parseDocsReviewArgs(argv) {
1042
1099
  continue;
1043
1100
  }
1044
1101
 
1102
+ if (token === '--rebuild') {
1103
+ parsed.rebuild = true;
1104
+ continue;
1105
+ }
1106
+
1107
+ if (token === '--dry-run') {
1108
+ parsed.dryRun = true;
1109
+ continue;
1110
+ }
1111
+
1112
+ if (token === '--apply') {
1113
+ parsed.apply = true;
1114
+ continue;
1115
+ }
1116
+
1045
1117
  if (token === '--apply-decision-artifact') {
1046
1118
  parsed.applyDecisionArtifact = true;
1047
1119
  continue;
@@ -1081,9 +1153,18 @@ function parseDocsReviewArgs(argv) {
1081
1153
  case '--output':
1082
1154
  parsed.outputPath = value;
1083
1155
  break;
1156
+ case '--path':
1157
+ parsed.scopePath = value;
1158
+ break;
1159
+ case '--stale-policy':
1160
+ parsed.stalePolicy = value;
1161
+ break;
1084
1162
  case '--artifact':
1085
1163
  parsed.artifactId = value;
1086
1164
  break;
1165
+ case '--sync-target':
1166
+ parsed.syncTarget = value;
1167
+ break;
1087
1168
  case '--max-tokens':
1088
1169
  parsed.maxTokens = value;
1089
1170
  break;
@@ -1101,7 +1182,72 @@ function parseDocsReviewArgs(argv) {
1101
1182
  function parsePushArgs(argv) {
1102
1183
  return {
1103
1184
  command: 'push',
1104
- options: parseRootOnlyArgs(argv, 'push'),
1185
+ options: parseRootAndSyncTargetArgs(argv, 'push'),
1186
+ };
1187
+ }
1188
+
1189
+ function parseRootAndSyncTargetArgs(argv, commandName) {
1190
+ const parsed = {};
1191
+
1192
+ for (let index = 0; index < argv.length; index += 1) {
1193
+ const token = argv[index];
1194
+ if (!token.startsWith('--')) {
1195
+ throw new Error(`Unexpected argument "${token}".`);
1196
+ }
1197
+
1198
+ const value = argv[index + 1];
1199
+ if (value === undefined) {
1200
+ throw new Error(`Flag "${token}" requires a value.`);
1201
+ }
1202
+ index += 1;
1203
+
1204
+ switch (token) {
1205
+ case '--root':
1206
+ parsed.rootDir = value;
1207
+ break;
1208
+ case '--sync-target':
1209
+ parsed.syncTarget = value;
1210
+ break;
1211
+ default:
1212
+ throw new Error(`Unknown flag "${token}" for ${commandName}.`);
1213
+ }
1214
+ }
1215
+
1216
+ return parsed;
1217
+ }
1218
+
1219
+ function parseSyncTargetArgs(argv) {
1220
+ const parsed = {};
1221
+
1222
+ for (let index = 0; index < argv.length; index += 1) {
1223
+ const token = argv[index];
1224
+
1225
+ if (!token.startsWith('--')) {
1226
+ if (parsed.targetName !== undefined) {
1227
+ throw new Error(`Unexpected argument "${token}".`);
1228
+ }
1229
+ parsed.targetName = token;
1230
+ continue;
1231
+ }
1232
+
1233
+ const value = argv[index + 1];
1234
+ if (value === undefined) {
1235
+ throw new Error(`Flag "${token}" requires a value.`);
1236
+ }
1237
+ index += 1;
1238
+
1239
+ switch (token) {
1240
+ case '--root':
1241
+ parsed.rootDir = value;
1242
+ break;
1243
+ default:
1244
+ throw new Error(`Unknown flag "${token}" for sync-target.`);
1245
+ }
1246
+ }
1247
+
1248
+ return {
1249
+ command: 'sync-target',
1250
+ options: parsed,
1105
1251
  };
1106
1252
  }
1107
1253
 
@@ -1129,6 +1275,9 @@ function parsePullPreviewArgs(argv) {
1129
1275
  case '--root':
1130
1276
  parsed.rootDir = value;
1131
1277
  break;
1278
+ case '--sync-target':
1279
+ parsed.syncTarget = value;
1280
+ break;
1132
1281
  default:
1133
1282
  throw new Error(`Unknown flag "${token}".`);
1134
1283
  }
@@ -1162,6 +1311,9 @@ function parsePullExportArgs(argv) {
1162
1311
  case '--root':
1163
1312
  parsed.rootDir = value;
1164
1313
  break;
1314
+ case '--sync-target':
1315
+ parsed.syncTarget = value;
1316
+ break;
1165
1317
  case '--preview-token':
1166
1318
  parsed.previewToken = value;
1167
1319
  break;
@@ -1320,6 +1472,7 @@ function usageText() {
1320
1472
  'Usage:',
1321
1473
  ' vibecompass init --name <project-name> --mode <local-only|local-primary|hosted-only> --repo <id=remote> [options]',
1322
1474
  ' vibecompass connect-hosted [options]',
1475
+ ' vibecompass sync-target [<name>] [options]',
1323
1476
  ' vibecompass status [options]',
1324
1477
  ' vibecompass refresh-workflow [--dry-run|--apply] [options]',
1325
1478
  ' vibecompass start-session --id <lane-id> --working-on <text> [options]',
@@ -1361,10 +1514,17 @@ function usageText() {
1361
1514
  '',
1362
1515
  'Connect-hosted options:',
1363
1516
  ' --root <path> Project-memory root. Defaults to .compass',
1517
+ ' --target <name> Add or update a named sync target (e.g. dev, prod)',
1518
+ ' First named target becomes the default; flat sync fields mirror the default target',
1364
1519
  ' --sync-api-url <url> Hosted sync api_url',
1365
1520
  ' --sync-project-id <id> Hosted sync project_id',
1366
1521
  ' --sync-credential-env-var <name> Hosted sync env var reference',
1367
- ' Replaces any existing project.yaml sync binding',
1522
+ ' Without --target, replaces any existing flat project.yaml sync binding',
1523
+ '',
1524
+ 'Sync-target options:',
1525
+ ' vibecompass sync-target List named sync targets and the current default',
1526
+ ' vibecompass sync-target <name> Switch the default sync target (re-mirrors flat sync fields)',
1527
+ ' --root <path> Project-memory root. Defaults to .compass',
1368
1528
  '',
1369
1529
  'Status options:',
1370
1530
  ' --root <path> Project-memory root. Defaults to .compass',
@@ -1419,6 +1579,7 @@ function usageText() {
1419
1579
  '',
1420
1580
  'Sync transport options:',
1421
1581
  ' push --root <path> Push canonical local project memory to hosted',
1582
+ ' --sync-target <name> Use a named sync target for this command (push, pull-preview, pull-export, docs-review)',
1422
1583
  ' pull-preview --root <path> Preview hosted proposals and remote state',
1423
1584
  ' pull-preview --no-pending-proposals Exclude pending proposals from preview',
1424
1585
  ' pull-export --proposal <id> Export a selected proposal; repeatable',
@@ -1437,6 +1598,11 @@ function usageText() {
1437
1598
  ' --run-local-anthropic Compatibility alias for --run-local --provider anthropic',
1438
1599
  ' --apply-output Apply accepted architecture doc blocks from review output',
1439
1600
  ' --output <path> Review output path for --apply-output; defaults to state/docs-review-output.md',
1601
+ ' --rebuild Preview or prepare an explicit architecture-doc rebuild',
1602
+ ' --dry-run Preview docs-review rebuild changes; default with --rebuild',
1603
+ ' --apply Apply docs-review rebuild preparation; only valid with --rebuild',
1604
+ ' --path <architecture/path> Scope --rebuild to an architecture directory',
1605
+ ' --stale-policy <keep|archive> Rebuild stale-doc handling; defaults to keep',
1440
1606
  ' --apply-decision-artifact Append an accepted hosted decision artifact locally',
1441
1607
  ' --artifact <id> Artifact ID for --apply-decision-artifact',
1442
1608
  ' --refresh-index Also regenerate decisions/INDEX.md after applying a decision artifact',