@vibecompass/vibecompass 0.13.1 → 0.15.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 CHANGED
@@ -1,6 +1,101 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.15.0 - 2026-09-25
4
+
5
+ - Add a layered local credential store for hosted sync tokens (D-355). Every
6
+ hosted command now resolves the token in a fixed order: the binding's env
7
+ var when set (per-shell override for CI, automation, and agents), then the
8
+ per-user credential store keyed by hosted URL + project id. The store lives
9
+ outside every project root (`VIBECOMPASS_CONFIG_DIR`, else
10
+ `$XDG_CONFIG_HOME/vibecompass`, else `~/.config/vibecompass`;
11
+ `%APPDATA%\vibecompass` on Windows); its `credentials.json` index is
12
+ written `0600` inside a `0700` directory and a world-readable file is
13
+ refused. Secrets go to the OS keychain when one is available (macOS
14
+ Keychain via `security`, Linux `secret-tool`) and otherwise into the file;
15
+ the index records which backend holds each entry. `project.yaml` is
16
+ unchanged (`credential_source: env` + `credential_env_var` stay required),
17
+ so older CLIs keep working against the env var.
18
+ - `connect-hosted` captures the token after writing the binding: a hidden
19
+ prompt on a TTY, `--token-stdin` for scripts and agents, `--no-store` to
20
+ keep the env-only path, and `--credential-store <auto|keychain|file>`.
21
+ When the env var is already set it says so and points at
22
+ `sync-credential set --from-env` instead of storing silently.
23
+ - Add `vibecompass login [--sync-target <name>] [--api-url <url>]
24
+ [--project-id <id>] [--label <text>] [--no-browser] [--poll-timeout <s>]`:
25
+ a browser device-code sign-in. The CLI prints and opens the dashboard
26
+ approval link with a short code, polls until the project owner approves,
27
+ stores the minted token, and writes the sync binding when the root is not
28
+ bound yet (promoting `local-only` to `local-primary` like `connect-hosted`).
29
+ An unknown `--sync-target` is created only with an explicit `--api-url`;
30
+ a mismatched `--api-url` on a bound root fails closed.
31
+ - Add `vibecompass sync-credential <set|remove|list>`: store a dashboard
32
+ token (hidden prompt, `--token-stdin`, or `--from-env`), forget one, or
33
+ list stored entries (metadata only, never values; `--json`). `--api-url`
34
+ + `--project-id` address a hosted project without a bound root.
35
+ - `status` prints `Hosted sync:` and `Sync credential:` lines (source only:
36
+ env var, OS keychain, credential store file, or missing) and recommends
37
+ `vibecompass login` when nothing holds a token. Missing-credential errors
38
+ from push, pull, mode transitions, and hosted docs-review now name
39
+ `login` first, then `sync-credential set`, then the env var override.
40
+ - Init and connect-hosted no longer tell users to export the token in
41
+ every terminal or persist it in a shell profile.
42
+ - Credential store hardening (review passes 1–3): every store mutation
43
+ takes a cross-process lock file next to the index that appears atomically
44
+ (owner record hard-linked into place) and names its owner (id, pid, host).
45
+ The lock is never taken from a live process on this host, however long it
46
+ waits on a keychain prompt; writers wait up to 10s, then fail naming the
47
+ owner. A lock whose owner process no longer exists is recovered through a
48
+ second reclaim lock so exactly one reclaimer removes it after re-reading
49
+ the owner; locks from another host, unreadable locks, and a reclaim lock
50
+ left by a crashed reclaimer are never removed automatically (the error
51
+ names them). The index is written through an exclusively created random
52
+ temp file plus atomic rename while the lock is held, so parallel logins,
53
+ `sync-credential set`, and `remove` never drop each other's entries;
54
+ target identity lowercases only scheme and host (paths keep their case);
55
+ keychain labels are sanitized and keys outside the keychain-safe charset
56
+ map to a digest account, so any project name can be stored; under the
57
+ default `auto` policy a failed keychain write (headless session, locked
58
+ keychain, missing Secret Service) falls back to the file store with a
59
+ printed warning instead of losing a one-time claim. `login` bounds every
60
+ network wait (start, polls, body reads) by `--poll-timeout`.
61
+ - `login` is the one recommended connection path (D-356): help lists it
62
+ right after `init`, `init` and missing-token errors point only at it, and
63
+ `connect-hosted` on a terminal starts the browser sign-in when you press
64
+ Enter at its token prompt. Dashboard tokens, `--token-stdin`,
65
+ `sync-credential`, and the env-var override remain for CI, scripts, and
66
+ browserless machines and are labelled advanced.
67
+
68
+ ## 0.14.0 - 2026-09-23
69
+
70
+ - Add `continue-session [<lane-id>]` (D-353): resume an already-open lane
71
+ through the D-277 resolver (explicit id → worktree marker → single lane).
72
+ The lane keeps its opening date and session number; the command records
73
+ `resumed_at` / `resume_count` in `session.yaml`, appends a dated `Resumed`
74
+ line to `wip.md ## Log`, moves the index `current` hint and the Current
75
+ session block to the lane (showing the resume date), optionally refreshes
76
+ `--working-on`, prints the wip/handoff/latest-note paths plus runtime and
77
+ git-binding reminders, re-emits the docs-update staleness set as
78
+ `Resume staleness` warnings, and supports `--json`. With two or more active
79
+ lanes and no selection, or with an unknown explicit id, it fails closed and
80
+ prints the lane inventory. All inputs are read and outputs prepared before
81
+ the first write, so a refusal (missing CLAUDE.md, unparseable scratch or
82
+ metadata) changes no bytes; `--working-on` text is written literally,
83
+ hand-spaced or CRLF metadata keys are replaced rather than duplicated, and
84
+ Current-session fields carry over only for the exact same lane id.
85
+ - `list-sessions` renders the shared lane inventory (opened date/session
86
+ number, resume count, branch/worktrees, port, last log line, current hint)
87
+ and accepts `--json`; the header now says `current hint`.
88
+ - `start-session --id <existing-lane>` fails closed before any preflight and
89
+ names `continue-session`; starting a lane while others are active warns with
90
+ the resume alternative.
91
+ - Generated `context.md` gains an "Open, resume, or choose" protocol and a
92
+ `continue session` prompt command; the managed agent block gains the
93
+ matching hard rule (resume instead of re-start; with 2+ lanes inventory and
94
+ ask, never adopt the current hint silently).
95
+ - Report byte-identical managed agent instruction files as `unchanged` from
96
+ `sync-agents`, `refresh-workflow`, and session lifecycle syncs instead of
97
+ reporting a no-op as `update` / `dry-run-update`; missing or incomplete
98
+ managed markers remain warning-only and are never overwritten.
4
99
 
5
100
  ## 0.13.1 - 2026-09-11
6
101
 
package/README.md CHANGED
@@ -128,11 +128,21 @@ npx -y @vibecompass/vibecompass@latest status --root .compass
128
128
 
129
129
  # Session workflow
130
130
  npx -y @vibecompass/vibecompass@latest start-session --root .compass --id auth-flow --working-on "Auth flow"
131
- npx -y @vibecompass/vibecompass@latest list-sessions --root .compass
131
+ npx -y @vibecompass/vibecompass@latest list-sessions --root .compass # --json for the machine-readable lane inventory
132
+ npx -y @vibecompass/vibecompass@latest continue-session --root .compass # resume the open lane (D-353); name it with 2+ lanes: continue-session auth-flow
132
133
  npx -y @vibecompass/vibecompass@latest switch-session auth-flow --root .compass
133
134
  npx -y @vibecompass/vibecompass@latest docs-update --root .compass --session auth-flow
134
135
  npx -y @vibecompass/vibecompass@latest close-session --root .compass --session auth-flow --title "Auth Flow" --completed "Built auth" --architecture-docs updated --decision-log not-needed --session-maintenance updated --next-step "Review"
135
136
 
137
+ # Resuming (D-353): an active lane is an open session, not a crash. continue-session
138
+ # keeps the lane's opening date and session number, records resumed_at/resume_count
139
+ # in session.yaml, appends a dated "Resumed" line to wip.md, moves the index current
140
+ # hint and the Current session block to the lane, and prints the files to read next
141
+ # plus resume-staleness warnings. With two or more active lanes and no worktree
142
+ # marker it fails closed and prints the lane inventory instead of guessing;
143
+ # start-session --id <existing-lane> fails closed and points at continue-session.
144
+ npx -y @vibecompass/vibecompass@latest continue-session auth-flow --root .compass --working-on "Auth flow, phase 2"
145
+
136
146
  # Optional git binding for a lane (D-281): create/reuse a branch in each bound
137
147
  # repo; --worktree provisions per-repo worktrees under
138
148
  # <workspace>/worktrees/<lane-id>/<repo-id> with the lane marker in the
@@ -233,7 +243,22 @@ maintenance tied to the current lane.
233
243
  ## Hosted Sync
234
244
 
235
245
  Use hosted sync when you want browser review, team workflows, or hosted
236
- docs-review proposals:
246
+ docs-review proposals. The quickest path signs you in from the terminal and
247
+ keeps the token in your OS keychain (or a private per-user file), so it works
248
+ in every new terminal and in agents launched from a desktop app:
249
+
250
+ ```bash
251
+ npx -y @vibecompass/vibecompass@latest login --root .compass
252
+ # opens vibecompass.dev, you confirm a short code and pick the project,
253
+ # the token is stored locally, and the hosted binding is written to project.yaml
254
+
255
+ npx -y @vibecompass/vibecompass@latest push --root .compass
256
+ ```
257
+
258
+ Advanced (CI, scripts, a machine without a browser, or a hosted-only demote):
259
+ bind the root with a dashboard-created token, pasted at the hidden prompt or
260
+ piped in. On a terminal, pressing Enter at that prompt starts the browser
261
+ sign-in instead:
237
262
 
238
263
  ```bash
239
264
  npx -y @vibecompass/vibecompass@latest connect-hosted \
@@ -241,8 +266,12 @@ npx -y @vibecompass/vibecompass@latest connect-hosted \
241
266
  --sync-api-url https://vibecompass.dev \
242
267
  --sync-project-id vc_proj_example \
243
268
  --sync-credential-env-var VIBECOMPASS_SYNC_TOKEN
269
+ # "Paste the sync token from the dashboard (input hidden)"
244
270
 
245
- npx -y @vibecompass/vibecompass@latest push --root .compass
271
+ # non-interactive:
272
+ printf '%s' "$TOKEN" | npx -y @vibecompass/vibecompass@latest connect-hosted --root .compass \
273
+ --sync-api-url https://vibecompass.dev --sync-project-id vc_proj_example \
274
+ --sync-credential-env-var VIBECOMPASS_SYNC_TOKEN --token-stdin
246
275
  ```
247
276
 
248
277
  After `close-session`, run `push` again when a connected local-primary root
@@ -250,16 +279,29 @@ changed canonical project-memory files and the hosted dashboard should catch
250
279
  up. Hosted-only projects do not use a local authoritative push; update or
251
280
  refresh them through the hosted dashboard/proposal flow.
252
281
 
253
- The sync token is read from the environment variable you bind (for example
254
- `VIBECOMPASS_SYNC_TOKEN`). One-off `export`s do not survive new terminals —
255
- persist the token in your shell profile (`~/.zshenv` or `~/.bashrc`):
282
+ ### Where the token lives (D-355)
283
+
284
+ Hosted commands look for the token in this order:
285
+
286
+ 1. the environment variable named in `project.yaml` (`VIBECOMPASS_SYNC_TOKEN`
287
+ by default) — a per-shell override for CI and scripts;
288
+ 2. the local credential store, keyed by hosted URL + project id: the OS
289
+ keychain when available (macOS Keychain, Linux `secret-tool`), otherwise
290
+ `~/.config/vibecompass/credentials.json` (`0600`; `%APPDATA%\vibecompass`
291
+ on Windows; `VIBECOMPASS_CONFIG_DIR` overrides the location).
292
+
293
+ The token value is never written to `project.yaml`, `state/`, or any file in
294
+ your repo. Manage stored tokens with:
256
295
 
257
296
  ```bash
258
- echo 'export VIBECOMPASS_SYNC_TOKEN="<your sync token>"' >> ~/.zshenv
297
+ npx -y @vibecompass/vibecompass@latest sync-credential list --root .compass
298
+ npx -y @vibecompass/vibecompass@latest sync-credential set --root .compass # hidden prompt, --token-stdin, or --from-env
299
+ npx -y @vibecompass/vibecompass@latest sync-credential remove --root .compass
259
300
  ```
260
301
 
261
- If the token is lost, rotate it on the hosted dashboard under Setup -> Hosted
262
- sync and export the new value.
302
+ `vibecompass status` shows which source is in use (never the value). Lost a
303
+ token? Run `login` again, or create a new one on the dashboard under Setup ->
304
+ Hosted sync and revoke the old one there.
263
305
 
264
306
  ### Multiple environments
265
307
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecompass/vibecompass",
3
- "version": "0.13.1",
3
+ "version": "0.15.0",
4
4
  "description": "Local-first project-memory core for VibeCompass",
5
5
  "type": "module",
6
6
  "bin": {