@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/CHANGELOG.md +14 -0
- package/README.md +95 -691
- package/package.json +1 -1
- package/src/cli.js +170 -4
- package/src/docs-review.js +641 -24
- package/src/init.js +139 -1
- package/src/setup.js +1 -0
- package/src/status.js +55 -1
- package/src/sync-binding.js +307 -0
- package/src/sync.js +31 -24
- package/src/workflows/registry.js +9 -5
package/package.json
CHANGED
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
|
-
|
|
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:
|
|
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
|
-
'
|
|
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',
|