jaitus 0.3.18 → 0.3.19

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 (2) hide show
  1. package/package.json +2 -2
  2. package/src/machine.js +35 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaitus",
3
- "version": "0.3.18",
3
+ "version": "0.3.19",
4
4
  "description": "Jaitus — a coding agent in your terminal.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,7 @@
16
16
  "node": ">=20"
17
17
  },
18
18
  "scripts": {
19
- "test": "node tests/source-sanity.js && node tests/react-build.js && node tests/stalls.js && node tests/clipboard-write.js && node tests/rewind-images.js && node tests/rules.js && node tests/run.js && node tests/commands.js && node tests/login.js && node tests/session.js && node tests/openUrl.js && node tests/ink-tui.js && node tests/tui-render.js && node tests/mouse-e2e.js && node tests/environment.js && node tests/update.js && node tests/service-notices.js && node tests/continuation.js && node tests/steps.js && node tests/files.js && node tests/processes.js && node tests/security.js && node tests/context-budget.js && node tests/context-trim.js && node tests/compaction.js && node tests/copy-clean.js && node tests/parallel-tools.js && node tests/plan-percent.js",
19
+ "test": "node tests/source-sanity.js && node tests/react-build.js && node tests/stalls.js && node tests/clipboard-write.js && node tests/rewind-images.js && node tests/rules.js && node tests/run.js && node tests/commands.js && node tests/login.js && node tests/session.js && node tests/openUrl.js && node tests/ink-tui.js && node tests/tui-render.js && node tests/mouse-e2e.js && node tests/environment.js && node tests/update.js && node tests/service-notices.js && node tests/continuation.js && node tests/steps.js && node tests/files.js && node tests/processes.js && node tests/security.js && node tests/context-budget.js && node tests/context-trim.js && node tests/compaction.js && node tests/copy-clean.js && node tests/parallel-tools.js && node tests/plan-percent.js && node tests/project-identity.js",
20
20
  "preview": "node scripts/tui-preview.js",
21
21
  "prepublishOnly": "npm test"
22
22
  },
package/src/machine.js CHANGED
@@ -11,6 +11,7 @@
11
11
  // folder), each restoring the other
12
12
  // n the address of each physical network adapter (virtual and randomised ones are
13
13
  // skipped: they change by themselves)
14
+ // r the first commit of the git project the CLI runs in (and its regular authors, as g)
14
15
  // g the git identity this computer commits as (global user.email) — the same on
15
16
  // every computer one person sets up, so it recognises the person, not the machine
16
17
  //
@@ -154,6 +155,35 @@ function gitIdentity() {
154
155
  } catch { return null; }
155
156
  }
156
157
 
158
+ // Commit authors that are services, not people.
159
+ const BOT_EMAIL = /(\[bot\]|noreply@github\.com$|^actions@|dependabot|renovate|github-actions|@users\.noreply\.gitlab\.com$|^git@)/i;
160
+
161
+ /**
162
+ * The project this CLI runs in, if it is a git repository:
163
+ * roots its first commit(s) — the same on every clone, on every computer
164
+ * authors the people who commit to it most (last 300 commits), so a person is known by
165
+ * the work they come back to even after changing the global git identity
166
+ * The server treats a project or author seen on many unrelated accounts as public (an
167
+ * open-source repository cloned by strangers) and links nobody through it.
168
+ */
169
+ export function projectIdentity(cwd = process.cwd()) {
170
+ const git = (args) => {
171
+ try {
172
+ const r = spawnSync('git', args, { cwd, encoding: 'utf8', timeout: 2000, windowsHide: true });
173
+ return r.status === 0 ? String(r.stdout || '') : '';
174
+ } catch { return ''; }
175
+ };
176
+ const roots = git(['rev-list', '--max-parents=0', 'HEAD']).split(/\s+/).filter((s) => /^[0-9a-f]{40,64}$/.test(s)).sort().slice(0, 2);
177
+ const counts = new Map();
178
+ for (const line of git(['log', '-n', '300', '--format=%ae']).split('\n')) {
179
+ const e = line.trim().toLowerCase();
180
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) || PLACEHOLDER_EMAIL.test(e) || BOT_EMAIL.test(e)) continue;
181
+ counts.set(e, (counts.get(e) || 0) + 1);
182
+ }
183
+ const authors = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(([e]) => e);
184
+ return { roots, authors };
185
+ }
186
+
157
187
  /**
158
188
  * Where the install id's second copy lives: outside ~/.jaitus, in the OS's app-data
159
189
  * folder. Always under os.homedir() (not LOCALAPPDATA / XDG_DATA_HOME), so a test run
@@ -215,6 +245,11 @@ export function machineHeader() {
215
245
  if (soft) parts.push(`s=${hash('s', soft)}`);
216
246
  const git = gitIdentity();
217
247
  if (git) parts.push(`g=${hash('g', git)}`);
248
+ // r: the project's first commit; its regular authors are git identities like the one
249
+ // above (same kind, same hash), so they match a git identity seen on another computer.
250
+ const project = projectIdentity();
251
+ for (const root of project.roots) parts.push(`r=${hash('r', root)}`);
252
+ for (const a of project.authors) if (a !== git) parts.push(`g=${hash('g', a)}`);
218
253
  if (m && cache.m !== m) writeCache({ ...cache, m, ...(h ? { h } : {}) });
219
254
  } catch { /* whatever was gathered */ }
220
255
  header = parts.join(',');