@ibgib/vcs-gib 0.0.6

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.
Files changed (202) hide show
  1. package/README.md +94 -0
  2. package/VCS_CLI_USER_GUIDE.md +198 -0
  3. package/dist/AUTO-GENERATED-version.d.mts +6 -0
  4. package/dist/AUTO-GENERATED-version.d.mts.map +1 -0
  5. package/dist/AUTO-GENERATED-version.mjs +6 -0
  6. package/dist/AUTO-GENERATED-version.mjs.map +1 -0
  7. package/dist/assumptions.respec.d.mts +2 -0
  8. package/dist/assumptions.respec.d.mts.map +1 -0
  9. package/dist/assumptions.respec.mjs +41 -0
  10. package/dist/assumptions.respec.mjs.map +1 -0
  11. package/dist/bootstrap/node-bootstrap.d.mts +35 -0
  12. package/dist/bootstrap/node-bootstrap.d.mts.map +1 -0
  13. package/dist/bootstrap/node-bootstrap.mjs +165 -0
  14. package/dist/bootstrap/node-bootstrap.mjs.map +1 -0
  15. package/dist/bootstrap/node-bootstrap.respec.node.d.mts +7 -0
  16. package/dist/bootstrap/node-bootstrap.respec.node.d.mts.map +1 -0
  17. package/dist/bootstrap/node-bootstrap.respec.node.mjs +28 -0
  18. package/dist/bootstrap/node-bootstrap.respec.node.mjs.map +1 -0
  19. package/dist/cli/cli-arg-parser.d.mts +27 -0
  20. package/dist/cli/cli-arg-parser.d.mts.map +1 -0
  21. package/dist/cli/cli-arg-parser.mjs +96 -0
  22. package/dist/cli/cli-arg-parser.mjs.map +1 -0
  23. package/dist/cli/cli-arg-parser.respec.node.d.mts +7 -0
  24. package/dist/cli/cli-arg-parser.respec.node.d.mts.map +1 -0
  25. package/dist/cli/cli-arg-parser.respec.node.mjs +35 -0
  26. package/dist/cli/cli-arg-parser.respec.node.mjs.map +1 -0
  27. package/dist/cli/cli-constants.d.mts +26 -0
  28. package/dist/cli/cli-constants.d.mts.map +1 -0
  29. package/dist/cli/cli-constants.mjs +67 -0
  30. package/dist/cli/cli-constants.mjs.map +1 -0
  31. package/dist/cli/cli-e2e.respec.node.d.mts +8 -0
  32. package/dist/cli/cli-e2e.respec.node.d.mts.map +1 -0
  33. package/dist/cli/cli-e2e.respec.node.mjs +263 -0
  34. package/dist/cli/cli-e2e.respec.node.mjs.map +1 -0
  35. package/dist/cli/commands/add-cmd.d.mts +20 -0
  36. package/dist/cli/commands/add-cmd.d.mts.map +1 -0
  37. package/dist/cli/commands/add-cmd.mjs +333 -0
  38. package/dist/cli/commands/add-cmd.mjs.map +1 -0
  39. package/dist/cli/commands/branch-checkout-cmd.respec.node.d.mts +7 -0
  40. package/dist/cli/commands/branch-checkout-cmd.respec.node.d.mts.map +1 -0
  41. package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs +288 -0
  42. package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs.map +1 -0
  43. package/dist/cli/commands/branch-cmd.d.mts +25 -0
  44. package/dist/cli/commands/branch-cmd.d.mts.map +1 -0
  45. package/dist/cli/commands/branch-cmd.mjs +187 -0
  46. package/dist/cli/commands/branch-cmd.mjs.map +1 -0
  47. package/dist/cli/commands/checkout-cmd.d.mts +21 -0
  48. package/dist/cli/commands/checkout-cmd.d.mts.map +1 -0
  49. package/dist/cli/commands/checkout-cmd.mjs +154 -0
  50. package/dist/cli/commands/checkout-cmd.mjs.map +1 -0
  51. package/dist/cli/commands/commit-cmd.d.mts +23 -0
  52. package/dist/cli/commands/commit-cmd.d.mts.map +1 -0
  53. package/dist/cli/commands/commit-cmd.mjs +326 -0
  54. package/dist/cli/commands/commit-cmd.mjs.map +1 -0
  55. package/dist/cli/commands/commit-log-cmd.respec.node.d.mts +7 -0
  56. package/dist/cli/commands/commit-log-cmd.respec.node.d.mts.map +1 -0
  57. package/dist/cli/commands/commit-log-cmd.respec.node.mjs +251 -0
  58. package/dist/cli/commands/commit-log-cmd.respec.node.mjs.map +1 -0
  59. package/dist/cli/commands/init-cmd.d.mts +20 -0
  60. package/dist/cli/commands/init-cmd.d.mts.map +1 -0
  61. package/dist/cli/commands/init-cmd.mjs +119 -0
  62. package/dist/cli/commands/init-cmd.mjs.map +1 -0
  63. package/dist/cli/commands/init-cmd.respec.node.d.mts +7 -0
  64. package/dist/cli/commands/init-cmd.respec.node.d.mts.map +1 -0
  65. package/dist/cli/commands/init-cmd.respec.node.mjs +40 -0
  66. package/dist/cli/commands/init-cmd.respec.node.mjs.map +1 -0
  67. package/dist/cli/commands/log-cmd.d.mts +27 -0
  68. package/dist/cli/commands/log-cmd.d.mts.map +1 -0
  69. package/dist/cli/commands/log-cmd.mjs +146 -0
  70. package/dist/cli/commands/log-cmd.mjs.map +1 -0
  71. package/dist/cli/commands/status-add-cmd.respec.node.d.mts +7 -0
  72. package/dist/cli/commands/status-add-cmd.respec.node.d.mts.map +1 -0
  73. package/dist/cli/commands/status-add-cmd.respec.node.mjs +215 -0
  74. package/dist/cli/commands/status-add-cmd.respec.node.mjs.map +1 -0
  75. package/dist/cli/commands/status-cmd.d.mts +25 -0
  76. package/dist/cli/commands/status-cmd.d.mts.map +1 -0
  77. package/dist/cli/commands/status-cmd.mjs +286 -0
  78. package/dist/cli/commands/status-cmd.mjs.map +1 -0
  79. package/dist/cli/vcs-cli-main.d.mts +14 -0
  80. package/dist/cli/vcs-cli-main.d.mts.map +1 -0
  81. package/dist/cli/vcs-cli-main.mjs +136 -0
  82. package/dist/cli/vcs-cli-main.mjs.map +1 -0
  83. package/dist/engine/branch/branch-graph-helper.d.mts +19 -0
  84. package/dist/engine/branch/branch-graph-helper.d.mts.map +1 -0
  85. package/dist/engine/branch/branch-graph-helper.mjs +49 -0
  86. package/dist/engine/branch/branch-graph-helper.mjs.map +1 -0
  87. package/dist/engine/branch/branch-helper.d.mts +26 -0
  88. package/dist/engine/branch/branch-helper.d.mts.map +1 -0
  89. package/dist/engine/branch/branch-helper.mjs +57 -0
  90. package/dist/engine/branch/branch-helper.mjs.map +1 -0
  91. package/dist/engine/branch/branch-space-helper.d.mts +22 -0
  92. package/dist/engine/branch/branch-space-helper.d.mts.map +1 -0
  93. package/dist/engine/branch/branch-space-helper.mjs +77 -0
  94. package/dist/engine/branch/branch-space-helper.mjs.map +1 -0
  95. package/dist/engine/branch/branch-space.respec.node.d.mts +8 -0
  96. package/dist/engine/branch/branch-space.respec.node.d.mts.map +1 -0
  97. package/dist/engine/branch/branch-space.respec.node.mjs +138 -0
  98. package/dist/engine/branch/branch-space.respec.node.mjs.map +1 -0
  99. package/dist/engine/branch/branch-types.d.mts +26 -0
  100. package/dist/engine/branch/branch-types.d.mts.map +1 -0
  101. package/dist/engine/branch/branch-types.mjs +7 -0
  102. package/dist/engine/branch/branch-types.mjs.map +1 -0
  103. package/dist/engine/diff/line-diff-helper.d.mts +76 -0
  104. package/dist/engine/diff/line-diff-helper.d.mts.map +1 -0
  105. package/dist/engine/diff/line-diff-helper.mjs +144 -0
  106. package/dist/engine/diff/line-diff-helper.mjs.map +1 -0
  107. package/dist/engine/diff/line-diff-helper.respec.node.d.mts +7 -0
  108. package/dist/engine/diff/line-diff-helper.respec.node.d.mts.map +1 -0
  109. package/dist/engine/diff/line-diff-helper.respec.node.mjs +66 -0
  110. package/dist/engine/diff/line-diff-helper.respec.node.mjs.map +1 -0
  111. package/dist/engine/filter/glob-helper.d.mts +51 -0
  112. package/dist/engine/filter/glob-helper.d.mts.map +1 -0
  113. package/dist/engine/filter/glob-helper.mjs +132 -0
  114. package/dist/engine/filter/glob-helper.mjs.map +1 -0
  115. package/dist/engine/filter/glob-helper.respec.node.d.mts +7 -0
  116. package/dist/engine/filter/glob-helper.respec.node.d.mts.map +1 -0
  117. package/dist/engine/filter/glob-helper.respec.node.mjs +78 -0
  118. package/dist/engine/filter/glob-helper.respec.node.mjs.map +1 -0
  119. package/dist/engine/index/index-helper.d.mts +78 -0
  120. package/dist/engine/index/index-helper.d.mts.map +1 -0
  121. package/dist/engine/index/index-helper.mjs +289 -0
  122. package/dist/engine/index/index-helper.mjs.map +1 -0
  123. package/dist/engine/index/index-types.d.mts +63 -0
  124. package/dist/engine/index/index-types.d.mts.map +1 -0
  125. package/dist/engine/index/index-types.mjs +7 -0
  126. package/dist/engine/index/index-types.mjs.map +1 -0
  127. package/dist/engine/item/item-atom-helper.d.mts +20 -0
  128. package/dist/engine/item/item-atom-helper.d.mts.map +1 -0
  129. package/dist/engine/item/item-atom-helper.mjs +30 -0
  130. package/dist/engine/item/item-atom-helper.mjs.map +1 -0
  131. package/dist/engine/item/item-helper.d.mts +37 -0
  132. package/dist/engine/item/item-helper.d.mts.map +1 -0
  133. package/dist/engine/item/item-helper.mjs +194 -0
  134. package/dist/engine/item/item-helper.mjs.map +1 -0
  135. package/dist/engine/item/item-types.d.mts +127 -0
  136. package/dist/engine/item/item-types.d.mts.map +1 -0
  137. package/dist/engine/item/item-types.mjs +16 -0
  138. package/dist/engine/item/item-types.mjs.map +1 -0
  139. package/dist/index.d.mts +7 -0
  140. package/dist/index.d.mts.map +1 -0
  141. package/dist/index.mjs +7 -0
  142. package/dist/index.mjs.map +1 -0
  143. package/dist/respec-gib.node.d.mts +7 -0
  144. package/dist/respec-gib.node.d.mts.map +1 -0
  145. package/dist/respec-gib.node.mjs +11 -0
  146. package/dist/respec-gib.node.mjs.map +1 -0
  147. package/dist/vcs-gib-constants.d.mts +7 -0
  148. package/dist/vcs-gib-constants.d.mts.map +1 -0
  149. package/dist/vcs-gib-constants.mjs +7 -0
  150. package/dist/vcs-gib-constants.mjs.map +1 -0
  151. package/dist/vcs-gib.respec.node.d.mts +8 -0
  152. package/dist/vcs-gib.respec.node.d.mts.map +1 -0
  153. package/dist/vcs-gib.respec.node.mjs +82 -0
  154. package/dist/vcs-gib.respec.node.mjs.map +1 -0
  155. package/generate-version-file.js +20 -0
  156. package/package.json +28 -0
  157. package/src/AUTO-GENERATED-version.mts +5 -0
  158. package/src/assumptions.respec.mts +50 -0
  159. package/src/bootstrap/node-bootstrap.mts +198 -0
  160. package/src/bootstrap/node-bootstrap.respec.node.mts +35 -0
  161. package/src/cli/cli-arg-parser.mts +119 -0
  162. package/src/cli/cli-arg-parser.respec.node.mts +45 -0
  163. package/src/cli/cli-constants.mts +77 -0
  164. package/src/cli/cli-e2e.respec.node.mts +318 -0
  165. package/src/cli/commands/add-cmd.mts +415 -0
  166. package/src/cli/commands/branch-checkout-cmd.respec.node.mts +322 -0
  167. package/src/cli/commands/branch-cmd.mts +243 -0
  168. package/src/cli/commands/checkout-cmd.mts +202 -0
  169. package/src/cli/commands/commit-cmd.mts +421 -0
  170. package/src/cli/commands/commit-log-cmd.respec.node.mts +276 -0
  171. package/src/cli/commands/init-cmd.mts +152 -0
  172. package/src/cli/commands/init-cmd.respec.node.mts +49 -0
  173. package/src/cli/commands/log-cmd.mts +197 -0
  174. package/src/cli/commands/status-add-cmd.respec.node.mts +246 -0
  175. package/src/cli/commands/status-cmd.mts +366 -0
  176. package/src/cli/vcs-cli-main.mts +153 -0
  177. package/src/engine/branch/branch-graph-helper.mts +69 -0
  178. package/src/engine/branch/branch-helper.mts +79 -0
  179. package/src/engine/branch/branch-space-helper.mts +104 -0
  180. package/src/engine/branch/branch-space.respec.node.mts +158 -0
  181. package/src/engine/branch/branch-types.mts +29 -0
  182. package/src/engine/diff/line-diff-helper.mts +210 -0
  183. package/src/engine/diff/line-diff-helper.respec.node.mts +84 -0
  184. package/src/engine/filter/glob-helper.mts +165 -0
  185. package/src/engine/filter/glob-helper.respec.node.mts +94 -0
  186. package/src/engine/index/index-helper.mts +378 -0
  187. package/src/engine/index/index-types.mts +66 -0
  188. package/src/engine/item/item-atom-helper.mts +30 -0
  189. package/src/engine/item/item-helper.mts +239 -0
  190. package/src/engine/item/item-types.mts +136 -0
  191. package/src/index.mts +7 -0
  192. package/src/respec-gib.node.mts +12 -0
  193. package/src/vcs-gib-constants.mts +7 -0
  194. package/src/vcs-gib.respec.node.mts +96 -0
  195. package/test_runs/001-hello-node/20260728_090100_0001-flow-core-main.md +39 -0
  196. package/test_runs/001-hello-node/20260728_090200_0003-flow-branching-worktree.md +54 -0
  197. package/test_runs/001-hello-node/20260728_090300_0002-flow-selective-add.md +45 -0
  198. package/test_runs/001-hello-node/20260728_142100_0007-flow-edge-cases.md +44 -0
  199. package/test_runs/001-hello-node/20260728_142400_0005-flow-hardcoded-ignores.md +36 -0
  200. package/tools/pack-for-test.mjs +73 -0
  201. package/tsconfig.json +18 -0
  202. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,318 @@
1
+ /**
2
+ * @module cli-e2e.respec
3
+ *
4
+ * End-to-End CLI Integration Spec for @ibgib/vcs-gib.
5
+ * Executes full lifecycle: vcs init -> vcs status -> vcs add -> vcs commit -> vcs log -> vcs branch -> vcs checkout.
6
+ */
7
+
8
+ import path from 'node:path';
9
+ import fs from 'node:fs/promises';
10
+
11
+ import {
12
+ respecfully, ifWe, iReckon
13
+ } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
14
+
15
+ import { main } from './vcs-cli-main.mjs';
16
+ import { executeInitCmd } from './commands/init-cmd.mjs';
17
+ import { executeStatusCmd } from './commands/status-cmd.mjs';
18
+ import { executeAddCmd } from './commands/add-cmd.mjs';
19
+ import { executeCommitCmd } from './commands/commit-cmd.mjs';
20
+ import { executeLogCmd } from './commands/log-cmd.mjs';
21
+ import { executeBranchCmd } from './commands/branch-cmd.mjs';
22
+ import { executeCheckoutCmd } from './commands/checkout-cmd.mjs';
23
+ import { bootstrapVcsMetaspace } from '../bootstrap/node-bootstrap.mjs';
24
+ import { getB2tFSIndexIbGib } from '../engine/index/index-helper.mjs';
25
+
26
+ const lc = `[apps/vcs-gib/src/cli/cli-e2e.respec.node.mts]`;
27
+
28
+ await respecfully(lc, `Full E2E CLI Integration Spec`, async () => {
29
+
30
+ await ifWe(lc, `runs help and version flags without error`, async () => {
31
+ let helpCalled = false;
32
+ let versionCalled = false;
33
+
34
+ const origLog = console.log;
35
+ console.log = (...args: any[]) => {
36
+ const msg = args.join(' ');
37
+ if (msg.includes('Decentralized Version Control System')) {
38
+ helpCalled = true;
39
+ }
40
+ if (msg.includes('@ibgib/vcs-gib v0.0.4')) {
41
+ versionCalled = true;
42
+ }
43
+ };
44
+
45
+ try {
46
+ const helpExitCode = await main({ argv: ['--help'] });
47
+ iReckon(lc, helpExitCode).willEqual(0);
48
+
49
+ const versionExitCode = await main({ argv: ['--version'] });
50
+ iReckon(lc, versionExitCode).willEqual(0);
51
+ } finally {
52
+ console.log = origLog;
53
+ }
54
+
55
+ iReckon(lc, helpCalled).isGonnaBeTrue();
56
+ iReckon(lc, versionCalled).isGonnaBeTrue();
57
+ });
58
+
59
+ await ifWe(lc, `executes complete lifecycle: init -> status -> add -> commit -> log -> branch -> checkout`, async () => {
60
+ const testDir = path.join(process.cwd(), `.test_cli_e2e_${Date.now()}`);
61
+ const vcsFolderName = '.vcsgib_test_e2e';
62
+
63
+ try {
64
+ // Step 1: vcs init
65
+ const initRes = await executeInitCmd({
66
+ targetDir: testDir,
67
+ vcsFolderName,
68
+ quiet: true,
69
+ });
70
+ iReckon(lc, Boolean(initRes.vcsPath)).isGonnaBeTrue();
71
+ iReckon(lc, initRes.branchName).willEqual('main');
72
+
73
+ // Verify .vcsgib_test_e2e directory exists
74
+ const vcsExists = await fs.stat(initRes.vcsPath).then(s => s.isDirectory()).catch(() => false);
75
+ iReckon(lc, vcsExists).isGonnaBeTrue();
76
+
77
+ // Step 2: Create files & vcs status (untracked)
78
+ const readmePath = path.join(testDir, 'README.md');
79
+ const srcDirPath = path.join(testDir, 'src');
80
+ const appPath = path.join(srcDirPath, 'app.ts');
81
+
82
+ await fs.mkdir(srcDirPath, { recursive: true });
83
+ await fs.writeFile(readmePath, '# Sample Project\nWelcome to vcs-gib.', 'utf8');
84
+ await fs.writeFile(appPath, 'console.log("Hello ibgib!");', 'utf8');
85
+
86
+ const status1 = await executeStatusCmd({
87
+ targetDir: testDir,
88
+ vcsFolderName,
89
+ quiet: true,
90
+ });
91
+
92
+ iReckon(lc, status1.branchName).willEqual('main');
93
+ iReckon(lc, status1.staged.length).willEqual(0);
94
+ iReckon(lc, status1.untracked.length >= 2).isGonnaBeTrue();
95
+
96
+ const untrackedPaths = status1.untracked.map(u => u.path);
97
+ iReckon(lc, untrackedPaths).includes('README.md');
98
+ iReckon(lc, untrackedPaths).includes('src/app.ts');
99
+
100
+ // Step 3: vcs add <all>
101
+ const addRes = await executeAddCmd({
102
+ targetDir: testDir,
103
+ vcsFolderName,
104
+ all: true,
105
+ quiet: true,
106
+ });
107
+
108
+ iReckon(lc, addRes.stagedCount >= 2).isGonnaBeTrue();
109
+
110
+ const { localSpace: e2eSpaceAdd, vcsPath: e2eVcsPathAdd } = await bootstrapVcsMetaspace({
111
+ repoPath: testDir,
112
+ vcsFolderName,
113
+ });
114
+ const e2eIndexAdd = await getB2tFSIndexIbGib({ space: e2eSpaceAdd, vcsPath: e2eVcsPathAdd });
115
+ iReckon(lc, Boolean(e2eIndexAdd?.data?.staged_item && e2eIndexAdd.data.staged_item.length >= 2)).isGonnaBeTrue();
116
+ iReckon(lc, e2eIndexAdd?.rel8ns?.staged_item).isGonnaBeFalsy();
117
+
118
+ const status2 = await executeStatusCmd({
119
+ targetDir: testDir,
120
+ vcsFolderName,
121
+ quiet: true,
122
+ });
123
+ iReckon(lc, status2.staged.length >= 2).isGonnaBeTrue();
124
+
125
+ // Step 4: vcs commit -m "Initial commit"
126
+ const commitRes = await executeCommitCmd({
127
+ targetDir: testDir,
128
+ vcsFolderName,
129
+ message: 'Initial commit',
130
+ quiet: true,
131
+ });
132
+
133
+ const { localSpace: e2eSpaceCommit, vcsPath: e2eVcsPathCommit } = await bootstrapVcsMetaspace({
134
+ repoPath: testDir,
135
+ vcsFolderName,
136
+ });
137
+ const e2eIndexCommit = await getB2tFSIndexIbGib({ space: e2eSpaceCommit, vcsPath: e2eVcsPathCommit });
138
+ iReckon(lc, e2eIndexCommit?.data?.staged_item).willEqual([]);
139
+ iReckon(lc, e2eIndexCommit?.rel8ns?.staged_item).isGonnaBeFalsy();
140
+
141
+ iReckon(lc, Boolean(commitRes.commitAddr)).isGonnaBeTrue();
142
+ iReckon(lc, Boolean(commitRes.commentAddr)).isGonnaBeTrue();
143
+ iReckon(lc, commitRes.branchName).willEqual('main');
144
+
145
+ const status3 = await executeStatusCmd({
146
+ targetDir: testDir,
147
+ vcsFolderName,
148
+ quiet: true,
149
+ });
150
+ iReckon(lc, status3.staged.length).willEqual(0);
151
+ iReckon(lc, status3.modified.length).willEqual(0);
152
+ iReckon(lc, status3.untracked.length).willEqual(0);
153
+
154
+ // Step 5: vcs log
155
+ const logRes = await executeLogCmd({
156
+ targetDir: testDir,
157
+ vcsFolderName,
158
+ quiet: true,
159
+ });
160
+
161
+ iReckon(lc, logRes.branchName).willEqual('main');
162
+ iReckon(lc, logRes.commits.length).willEqual(1);
163
+ iReckon(lc, logRes.commits[0].message).willEqual('Initial commit');
164
+
165
+ // Step 6: vcs branch feature-ui
166
+ const branchRes = await executeBranchCmd({
167
+ targetDir: testDir,
168
+ vcsFolderName,
169
+ branchName: 'feature-ui',
170
+ quiet: true,
171
+ });
172
+
173
+ iReckon(lc, branchRes.createdBranchName).willEqual('feature-ui');
174
+
175
+ const listBranches = await executeBranchCmd({
176
+ targetDir: testDir,
177
+ vcsFolderName,
178
+ quiet: true,
179
+ });
180
+
181
+ iReckon(lc, listBranches.branches.length).willEqual(2);
182
+ const mainBranch = listBranches.branches.find(b => b.name === 'main');
183
+ const featureBranch = listBranches.branches.find(b => b.name === 'feature-ui');
184
+
185
+ iReckon(lc, mainBranch?.isActive).isGonnaBeTrue();
186
+ iReckon(lc, featureBranch?.isActive).isGonnaBeFalse();
187
+
188
+ // Step 7: vcs checkout feature-ui
189
+ const checkoutRes = await executeCheckoutCmd({
190
+ targetDir: testDir,
191
+ vcsFolderName,
192
+ branchName: 'feature-ui',
193
+ quiet: true,
194
+ });
195
+
196
+ iReckon(lc, checkoutRes.previousBranch).willEqual('main');
197
+ iReckon(lc, checkoutRes.currentBranch).willEqual('feature-ui');
198
+ iReckon(lc, Boolean(checkoutRes.worktreePath)).isGonnaBeTrue();
199
+
200
+ // Verify feature-ui is active now and both branches are listed
201
+ const listBranches2 = await executeBranchCmd({
202
+ targetDir: checkoutRes.worktreePath,
203
+ vcsFolderName,
204
+ quiet: true,
205
+ });
206
+
207
+ iReckon(lc, listBranches2.branches.length).willEqual(2);
208
+ const featureBranchActive = listBranches2.branches.find(b => b.name === 'feature-ui');
209
+ iReckon(lc, featureBranchActive?.isActive).isGonnaBeTrue();
210
+
211
+ // Checkout back to main and verify all branches listed
212
+ const checkoutMainRes = await executeCheckoutCmd({
213
+ targetDir: checkoutRes.worktreePath,
214
+ vcsFolderName,
215
+ branchName: 'main',
216
+ quiet: true,
217
+ });
218
+ iReckon(lc, checkoutMainRes.currentBranch).willEqual('main');
219
+
220
+ const listBranches3 = await executeBranchCmd({
221
+ targetDir: testDir,
222
+ vcsFolderName,
223
+ quiet: true,
224
+ });
225
+ iReckon(lc, listBranches3.branches.length).willEqual(2);
226
+
227
+ // Checkout back to feature-ui
228
+ await executeCheckoutCmd({
229
+ targetDir: testDir,
230
+ vcsFolderName,
231
+ branchName: 'feature-ui',
232
+ quiet: true,
233
+ });
234
+
235
+ // Verify worktree folder was created and contains project files
236
+ const worktreeReadme = path.join(checkoutRes.worktreePath, 'README.md');
237
+ const worktreeReadmeContent = await fs.readFile(worktreeReadme, 'utf8');
238
+ iReckon(lc, worktreeReadmeContent).includes('Sample Project');
239
+
240
+ // Verify dedicated branch space subfolders in .vcsgib_test_e2e
241
+ const e2eMainSpace = path.join(initRes.vcsPath, 'ibgib', 'b2s_main');
242
+ const e2eFeatureSpace = path.join(initRes.vcsPath, 'ibgib', 'b2s_feature-ui');
243
+ const e2eMainExists = await fs.stat(e2eMainSpace).then(s => s.isDirectory()).catch(() =>
244
+ fs.stat(path.join(initRes.vcsPath, 'b2s_main')).then(s => s.isDirectory()).catch(() => false)
245
+ );
246
+ const e2eFeatureExists = await fs.stat(e2eFeatureSpace).then(s => s.isDirectory()).catch(() =>
247
+ fs.stat(path.join(initRes.vcsPath, 'b2s_feature-ui')).then(s => s.isDirectory()).catch(() => false)
248
+ );
249
+ iReckon(lc, e2eMainExists).isGonnaBeTrue();
250
+ iReckon(lc, e2eFeatureExists).isGonnaBeTrue();
251
+
252
+ // Strict Workspace Isolation Assertion:
253
+ // ONLY vcsFolderName, 'b', 'README.md', and 'src' are allowed in testDir root.
254
+ // 'ibgib' must NOT spill into root!
255
+ const rootEntries = await fs.readdir(testDir);
256
+ const unexpectedRootEntries = rootEntries.filter(e =>
257
+ e !== vcsFolderName && e !== 'b' && e !== 'README.md' && e !== 'src'
258
+ );
259
+ iReckon(lc, unexpectedRootEntries).willEqual([]);
260
+ } finally {
261
+ await fs.rm(testDir, { recursive: true, force: true });
262
+ }
263
+ });
264
+
265
+ await ifWe(lc, `executes upward discovery and unmodified add check via CLI helpers`, async () => {
266
+ const testDir = path.join(process.cwd(), `.test_cli_e2e_fixes_${Date.now()}`);
267
+ const vcsFolderName = '.vcsgib_test_e2e_fixes';
268
+
269
+ try {
270
+ await executeInitCmd({
271
+ targetDir: testDir,
272
+ vcsFolderName,
273
+ quiet: true,
274
+ });
275
+
276
+ const srcDir = path.join(testDir, 'src');
277
+ await fs.mkdir(srcDir, { recursive: true });
278
+ await fs.writeFile(path.join(srcDir, 'index.ts'), 'console.log("e2e");', 'utf8');
279
+
280
+ // 1. Run add and commit
281
+ await executeAddCmd({
282
+ targetDir: testDir,
283
+ vcsFolderName,
284
+ all: true,
285
+ quiet: true,
286
+ });
287
+
288
+ await executeCommitCmd({
289
+ targetDir: testDir,
290
+ vcsFolderName,
291
+ message: 'Add index.ts',
292
+ quiet: true,
293
+ });
294
+
295
+ // 2. Upward discovery test: execute status from srcDir
296
+ const statusSub = await executeStatusCmd({
297
+ targetDir: srcDir,
298
+ vcsFolderName,
299
+ quiet: true,
300
+ });
301
+ iReckon(lc, statusSub.branchName).willEqual('main');
302
+ iReckon(lc, statusSub.untracked.length).willEqual(0);
303
+ iReckon(lc, statusSub.staged.length).willEqual(0);
304
+
305
+ // 3. Unmodified re-staging test: execute add -a on unchanged repo
306
+ const addAgain = await executeAddCmd({
307
+ targetDir: testDir,
308
+ vcsFolderName,
309
+ all: true,
310
+ quiet: true,
311
+ });
312
+ iReckon(lc, addAgain.stagedCount).willEqual(0);
313
+ } finally {
314
+ await fs.rm(testDir, { recursive: true, force: true });
315
+ }
316
+ });
317
+
318
+ });