@goodtek/vibeops 2.5.1 → 2.5.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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/lib/git-integration-sync.js +32 -14
- package/dist/lib/git.js +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to VibeOps are documented here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 2.5.2 - 2026-07-20
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`task add` / integration sync:** Governance-only dirt (`.vibeops.json`, `AGENTS.md`, `.vibeops/`, docs, `.cursor/rules/`) no longer blocks preflight. Right after `init`, `task add` works without stash. App-file dirt still fails and lists the blocking paths.
|
|
12
|
+
|
|
7
13
|
## 2.5.1 - 2026-07-20
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/README.md
CHANGED
|
@@ -111,7 +111,7 @@ vibeops task release
|
|
|
111
111
|
|
|
112
112
|
Only one TASK **In Progress** at a time (`task add` blocks otherwise). **Shipped** slices do not block the next add; merge on the host or with `task merge`, then optional `task sync`.
|
|
113
113
|
|
|
114
|
-
`task add` fast-forward-pulls the integration branch first. If that fails (diverged / dirty / local-ahead), it prints the cause and fix commands and **does not** create a TASK file. If a previous run left a TASK file without a branch, rerun `task add` to resume.
|
|
114
|
+
`task add` fast-forward-pulls the integration branch first. If that fails (diverged / **app** dirty / local-ahead), it prints the cause and fix commands and **does not** create a TASK file. VibeOps/governance-only changes (e.g. `.vibeops.json` after `init`) do **not** block. If a previous run left a TASK file without a branch, rerun `task add` to resume.
|
|
115
115
|
|
|
116
116
|
## Status
|
|
117
117
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { gitFetchRemote, gitLeftRightCount, gitPullFastForwardOnly, gitRemoteBranchExists, gitRemoteUrl, gitRevParse, gitSwitchToBranch, readGitInfo, } from "./git.js";
|
|
1
|
+
import { gitFetchRemote, gitGovernanceOnlyDirty, gitLeftRightCount, gitPullFastForwardOnly, gitRemoteBranchExists, gitRemoteUrl, gitRevParse, gitSwitchToBranch, readGitInfo, restoreGovernanceStashAfterSwitch, stashGovernanceIfBlocking, } from "./git.js";
|
|
2
2
|
import { cyan, dim, log } from "./logger.js";
|
|
3
3
|
function remoteRef(remote, branch) {
|
|
4
4
|
return `${remote}/${branch}`;
|
|
@@ -6,6 +6,9 @@ function remoteRef(remote, branch) {
|
|
|
6
6
|
/**
|
|
7
7
|
* Classify why `git pull --ff-only` would fail for the integration branch.
|
|
8
8
|
* Call after fetch when possible so `origin/branch` is current.
|
|
9
|
+
*
|
|
10
|
+
* Governance-only dirt (`.vibeops.json`, docs/, `.vibeops/`, …) does **not**
|
|
11
|
+
* block — `task add` right after `init` must work.
|
|
9
12
|
*/
|
|
10
13
|
export async function diagnoseIntegrationSync(cwd, remote, integrationBranch) {
|
|
11
14
|
if ((await gitRemoteUrl(cwd, remote)) === null) {
|
|
@@ -26,19 +29,28 @@ export async function diagnoseIntegrationSync(cwd, remote, integrationBranch) {
|
|
|
26
29
|
}
|
|
27
30
|
const git = await readGitInfo(cwd);
|
|
28
31
|
if (git.dirty === true) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const gov = await gitGovernanceOnlyDirty(cwd);
|
|
33
|
+
if (!gov.onlyGovernance) {
|
|
34
|
+
const blocking = gov.nonGovernancePaths.slice(0, 8);
|
|
35
|
+
const more = gov.nonGovernancePaths.length > blocking.length
|
|
36
|
+
? ` (+${gov.nonGovernancePaths.length - blocking.length} more)`
|
|
37
|
+
: "";
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
kind: "dirty",
|
|
41
|
+
summary: `Working tree has app changes — cannot fast-forward ${integrationBranch}.`,
|
|
42
|
+
fixes: [
|
|
43
|
+
"git status",
|
|
44
|
+
`# Blocking (non-governance): ${blocking.join(", ")}${more}`,
|
|
45
|
+
"git stash push -u -m \"vibeops: before sync\"",
|
|
46
|
+
`git checkout ${integrationBranch}`,
|
|
47
|
+
`git pull --ff-only ${remote} ${integrationBranch}`,
|
|
48
|
+
"git stash pop # if you stashed",
|
|
49
|
+
"vibeops task add",
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Governance-only dirty (.vibeops.json after init, docs, …) — proceed.
|
|
42
54
|
}
|
|
43
55
|
const localSha = await gitRevParse(cwd, integrationBranch);
|
|
44
56
|
const remoteSha = await gitRevParse(cwd, remoteRef(remote, integrationBranch));
|
|
@@ -129,6 +141,7 @@ export function printIntegrationSyncDiagnosis(d) {
|
|
|
129
141
|
/**
|
|
130
142
|
* Fetch + ensure local integration can be used as the base for a new task branch.
|
|
131
143
|
* Switches to the integration branch, then `--ff-only` pull when needed. Never force-resets.
|
|
144
|
+
* Governance-only dirt is stashed around switch/pull so post-`init` `.vibeops.json` edits do not block.
|
|
132
145
|
*/
|
|
133
146
|
export async function ensureIntegrationSynced(opts) {
|
|
134
147
|
const { cwd, remote, integrationBranch } = opts;
|
|
@@ -184,6 +197,8 @@ export async function ensureIntegrationSynced(opts) {
|
|
|
184
197
|
if (localSha !== null && remoteSha !== null && localSha === remoteSha) {
|
|
185
198
|
return { ok: true, diagnosis, pulled: false };
|
|
186
199
|
}
|
|
200
|
+
// Stash governance dirt so ff-only pull cannot be blocked by `.vibeops.json` etc.
|
|
201
|
+
const stashed = await stashGovernanceIfBlocking(cwd);
|
|
187
202
|
try {
|
|
188
203
|
await gitPullFastForwardOnly(cwd, remote, integrationBranch);
|
|
189
204
|
diagnosis = {
|
|
@@ -211,4 +226,7 @@ export async function ensureIntegrationSynced(opts) {
|
|
|
211
226
|
}
|
|
212
227
|
return { ok: false, diagnosis, pulled: false };
|
|
213
228
|
}
|
|
229
|
+
finally {
|
|
230
|
+
await restoreGovernanceStashAfterSwitch(cwd, stashed);
|
|
231
|
+
}
|
|
214
232
|
}
|
package/dist/lib/git.js
CHANGED
|
@@ -299,12 +299,17 @@ const GOVERNANCE_DOC_REL_PREFIXES = [
|
|
|
299
299
|
"docs/project/",
|
|
300
300
|
"docs/logs/",
|
|
301
301
|
".vibeops/",
|
|
302
|
+
".cursor/rules/",
|
|
302
303
|
];
|
|
304
|
+
/** Root files owned by vibeops init / config (not under `.vibeops/`). */
|
|
305
|
+
const GOVERNANCE_DOC_EXACT = new Set([".vibeops.json", "AGENTS.md"]);
|
|
303
306
|
function normalizeRepoRelPath(p) {
|
|
304
307
|
return p.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
305
308
|
}
|
|
306
309
|
export function isGovernanceDocumentationPath(repoRelativePath) {
|
|
307
310
|
const n = normalizeRepoRelPath(repoRelativePath);
|
|
311
|
+
if (GOVERNANCE_DOC_EXACT.has(n))
|
|
312
|
+
return true;
|
|
308
313
|
for (const prefix of GOVERNANCE_DOC_REL_PREFIXES) {
|
|
309
314
|
if (n.startsWith(prefix))
|
|
310
315
|
return true;
|