@ascenda-one/github-collector 0.1.12 → 0.1.14

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/dist/cli.js +430 -90
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -242,9 +242,28 @@ var require_afterHours = __commonJS({
242
242
  "../packages/tool-kit/out/afterHours.js"(exports) {
243
243
  "use strict";
244
244
  Object.defineProperty(exports, "__esModule", { value: true });
245
+ exports.BUSINESS_DAY = void 0;
246
+ exports.isOutsideBusinessHours = isOutsideBusinessHours;
245
247
  exports.isAfterHours = isAfterHours;
246
248
  exports.utcOffsetMinutesAt = utcOffsetMinutesAt;
247
249
  exports.localHourAt = localHourAt;
250
+ exports.BUSINESS_DAY = {
251
+ /** 0 = Sunday … 6 = Saturday. */
252
+ days: [1, 2, 3, 4, 5],
253
+ start: "09:00",
254
+ end: "17:00"
255
+ };
256
+ function isOutsideBusinessHours(at = /* @__PURE__ */ new Date(), opts = {}) {
257
+ const days = opts.days ?? exports.BUSINESS_DAY.days;
258
+ if (!days.includes(at.getDay()))
259
+ return true;
260
+ const minutes = at.getHours() * 60 + at.getMinutes();
261
+ const start = parseTimeToMinutes(opts.start ?? exports.BUSINESS_DAY.start, 9 * 60);
262
+ const end = parseTimeToMinutes(opts.end ?? exports.BUSINESS_DAY.end, 17 * 60);
263
+ if (start >= end)
264
+ return false;
265
+ return minutes < start || minutes >= end;
266
+ }
248
267
  function isAfterHours(now = /* @__PURE__ */ new Date(), start = "19:00", end = "07:00") {
249
268
  const currentMinutes = now.getHours() * 60 + now.getMinutes();
250
269
  const startMinutes = parseTimeToMinutes(start, 19 * 60);
@@ -847,6 +866,7 @@ var require_eventSender = __commonJS({
847
866
  utcOffsetMinutes: (0, afterHours_1.utcOffsetMinutesAt)(/* @__PURE__ */ new Date()),
848
867
  sessionId: identity.sessionId ?? void 0,
849
868
  workspaceHash: identity.workspaceHash ?? void 0,
869
+ projectHash: identity.projectHash ?? void 0,
850
870
  consentScope: tool_contract_1.ASCENDA_CONSENT_SCOPE,
851
871
  provenance: tool_contract_1.ASCENDA_PROVENANCE,
852
872
  privacyMode: "metadata_only",
@@ -902,6 +922,7 @@ var require_eventSender = __commonJS({
902
922
  severity: "low",
903
923
  sessionId: this.config.sessionId ?? void 0,
904
924
  workspaceHash: this.config.workspaceHash ?? void 0,
925
+ projectHash: this.config.projectHash ?? void 0,
905
926
  consentScope: tool_contract_1.ASCENDA_SEMANTIC_CONSENT_SCOPE,
906
927
  provenance: tool_contract_1.ASCENDA_SEMANTIC_PROVENANCE,
907
928
  privacyMode: "metadata_only",
@@ -931,6 +952,7 @@ var require_eventSender = __commonJS({
931
952
  severity: "low",
932
953
  sessionId: this.config.sessionId ?? void 0,
933
954
  workspaceHash: this.config.workspaceHash ?? void 0,
955
+ projectHash: this.config.projectHash ?? void 0,
934
956
  consentScope: tool_contract_1.ASCENDA_COLLABORATION_CONSENT_SCOPE,
935
957
  provenance: tool_contract_1.ASCENDA_PROVENANCE,
936
958
  privacyMode: "metadata_only",
@@ -1021,19 +1043,387 @@ var require_eventSender = __commonJS({
1021
1043
  }
1022
1044
  });
1023
1045
 
1046
+ // ../packages/tool-kit/out/contextRegistry.js
1047
+ var require_contextRegistry = __commonJS({
1048
+ "../packages/tool-kit/out/contextRegistry.js"(exports) {
1049
+ "use strict";
1050
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
1051
+ if (k2 === void 0) k2 = k;
1052
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1053
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1054
+ desc = { enumerable: true, get: function() {
1055
+ return m[k];
1056
+ } };
1057
+ }
1058
+ Object.defineProperty(o, k2, desc);
1059
+ } : function(o, m, k, k2) {
1060
+ if (k2 === void 0) k2 = k;
1061
+ o[k2] = m[k];
1062
+ });
1063
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
1064
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1065
+ } : function(o, v) {
1066
+ o["default"] = v;
1067
+ });
1068
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
1069
+ var ownKeys = function(o) {
1070
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1071
+ var ar = [];
1072
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1073
+ return ar;
1074
+ };
1075
+ return ownKeys(o);
1076
+ };
1077
+ return function(mod) {
1078
+ if (mod && mod.__esModule) return mod;
1079
+ var result = {};
1080
+ if (mod != null) {
1081
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1082
+ }
1083
+ __setModuleDefault(result, mod);
1084
+ return result;
1085
+ };
1086
+ }();
1087
+ Object.defineProperty(exports, "__esModule", { value: true });
1088
+ exports.workContextRegistryFilePath = workContextRegistryFilePath;
1089
+ exports.readWorkContextRegistry = readWorkContextRegistry;
1090
+ exports.recordWorkContext = recordWorkContext;
1091
+ exports.recordWorkContextAlias = recordWorkContextAlias;
1092
+ var fs = __importStar(__require("fs"));
1093
+ var os = __importStar(__require("os"));
1094
+ var path = __importStar(__require("path"));
1095
+ var MAX_PATHS_PER_ENTRY = 8;
1096
+ function workContextRegistryFilePath() {
1097
+ return path.join(os.homedir(), ".ascenda", "work-contexts.json");
1098
+ }
1099
+ function readWorkContextRegistry(registryFilePath = workContextRegistryFilePath()) {
1100
+ try {
1101
+ const parsed = JSON.parse(fs.readFileSync(registryFilePath, "utf8"));
1102
+ if (parsed && parsed.version === 1 && parsed.contexts && typeof parsed.contexts === "object") {
1103
+ return parsed;
1104
+ }
1105
+ } catch {
1106
+ }
1107
+ return { version: 1, contexts: {} };
1108
+ }
1109
+ function recordWorkContext(context, options) {
1110
+ if (!context)
1111
+ return false;
1112
+ const updates = [];
1113
+ if (context.projectHash && context.projectLabel) {
1114
+ updates.push({ hash: context.projectHash, kind: "project", label: context.projectLabel, observedPath: context.projectPath ?? context.workspacePath });
1115
+ }
1116
+ if (context.workspaceHash && context.workspaceLabel && context.workspaceHash !== context.projectHash) {
1117
+ updates.push({ hash: context.workspaceHash, kind: "workspace", label: context.workspaceLabel, observedPath: context.workspacePath });
1118
+ }
1119
+ return upsert(updates, options);
1120
+ }
1121
+ function recordWorkContextAlias(hash2, label, observedPath, options) {
1122
+ if (!hash2 || !label)
1123
+ return false;
1124
+ return upsert([{ hash: hash2, kind: "alias", label, observedPath: observedPath ?? null }], options);
1125
+ }
1126
+ function upsert(updates, options) {
1127
+ if (updates.length === 0)
1128
+ return false;
1129
+ try {
1130
+ const registryFilePath = options?.registryFilePath ?? workContextRegistryFilePath();
1131
+ const nowIso = (options?.now ?? /* @__PURE__ */ new Date()).toISOString();
1132
+ const registry = readWorkContextRegistry(registryFilePath);
1133
+ let dirty = false;
1134
+ for (const update of updates) {
1135
+ const existing = registry.contexts[update.hash];
1136
+ if (!existing) {
1137
+ registry.contexts[update.hash] = {
1138
+ kind: update.kind,
1139
+ label: update.label,
1140
+ paths: update.observedPath ? [update.observedPath] : [],
1141
+ firstSeenAt: nowIso,
1142
+ lastSeenAt: nowIso
1143
+ };
1144
+ dirty = true;
1145
+ continue;
1146
+ }
1147
+ if (existing.kind === "alias" && update.kind !== "alias") {
1148
+ existing.kind = update.kind;
1149
+ dirty = true;
1150
+ }
1151
+ if (existing.label !== update.label && update.kind !== "alias") {
1152
+ existing.label = update.label;
1153
+ dirty = true;
1154
+ }
1155
+ if (update.observedPath && !existing.paths.includes(update.observedPath)) {
1156
+ if (existing.paths.length < MAX_PATHS_PER_ENTRY)
1157
+ existing.paths.push(update.observedPath);
1158
+ dirty = true;
1159
+ }
1160
+ if (dayOf(existing.lastSeenAt) !== dayOf(nowIso)) {
1161
+ existing.lastSeenAt = nowIso;
1162
+ dirty = true;
1163
+ }
1164
+ }
1165
+ if (!dirty)
1166
+ return false;
1167
+ writeRegistry(registryFilePath, registry);
1168
+ return true;
1169
+ } catch {
1170
+ return false;
1171
+ }
1172
+ }
1173
+ function dayOf(iso) {
1174
+ return iso.slice(0, 10);
1175
+ }
1176
+ function writeRegistry(registryFilePath, registry) {
1177
+ const dir = path.dirname(registryFilePath);
1178
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
1179
+ const tmp = `${registryFilePath}.${process.pid}.tmp`;
1180
+ fs.writeFileSync(tmp, `${JSON.stringify(registry, null, 2)}
1181
+ `, { encoding: "utf8", mode: 384 });
1182
+ fs.renameSync(tmp, registryFilePath);
1183
+ if (process.platform !== "win32") {
1184
+ fs.chmodSync(registryFilePath, 384);
1185
+ }
1186
+ }
1187
+ }
1188
+ });
1189
+
1190
+ // ../packages/tool-kit/out/salt.js
1191
+ var require_salt = __commonJS({
1192
+ "../packages/tool-kit/out/salt.js"(exports) {
1193
+ "use strict";
1194
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
1195
+ if (k2 === void 0) k2 = k;
1196
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1197
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1198
+ desc = { enumerable: true, get: function() {
1199
+ return m[k];
1200
+ } };
1201
+ }
1202
+ Object.defineProperty(o, k2, desc);
1203
+ } : function(o, m, k, k2) {
1204
+ if (k2 === void 0) k2 = k;
1205
+ o[k2] = m[k];
1206
+ });
1207
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
1208
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1209
+ } : function(o, v) {
1210
+ o["default"] = v;
1211
+ });
1212
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
1213
+ var ownKeys = function(o) {
1214
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1215
+ var ar = [];
1216
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1217
+ return ar;
1218
+ };
1219
+ return ownKeys(o);
1220
+ };
1221
+ return function(mod) {
1222
+ if (mod && mod.__esModule) return mod;
1223
+ var result = {};
1224
+ if (mod != null) {
1225
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1226
+ }
1227
+ __setModuleDefault(result, mod);
1228
+ return result;
1229
+ };
1230
+ }();
1231
+ Object.defineProperty(exports, "__esModule", { value: true });
1232
+ exports.machineSaltFilePath = machineSaltFilePath;
1233
+ exports.readOrCreateMachineSalt = readOrCreateMachineSalt;
1234
+ exports.hashWithMachineSalt = hashWithMachineSalt;
1235
+ var crypto = __importStar(__require("crypto"));
1236
+ var fs = __importStar(__require("fs"));
1237
+ var os = __importStar(__require("os"));
1238
+ var path = __importStar(__require("path"));
1239
+ function machineSaltFilePath() {
1240
+ return path.join(os.homedir(), ".ascenda", "salt");
1241
+ }
1242
+ var cache = /* @__PURE__ */ new Map();
1243
+ function readOrCreateMachineSalt(saltFilePath = machineSaltFilePath()) {
1244
+ const hit = cache.get(saltFilePath);
1245
+ if (hit)
1246
+ return hit;
1247
+ const dir = path.dirname(saltFilePath);
1248
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
1249
+ let salt;
1250
+ try {
1251
+ salt = crypto.randomBytes(32).toString("hex");
1252
+ fs.writeFileSync(saltFilePath, salt, { encoding: "utf8", mode: 384, flag: "wx" });
1253
+ } catch (error) {
1254
+ if (error.code !== "EEXIST")
1255
+ throw error;
1256
+ salt = fs.readFileSync(saltFilePath, "utf8").trim();
1257
+ }
1258
+ if (process.platform !== "win32") {
1259
+ fs.chmodSync(dir, 448);
1260
+ fs.chmodSync(saltFilePath, 384);
1261
+ }
1262
+ cache.set(saltFilePath, salt);
1263
+ return salt;
1264
+ }
1265
+ function hashWithMachineSalt(value, saltFilePath) {
1266
+ if (!value)
1267
+ return null;
1268
+ return crypto.createHash("sha256").update(readOrCreateMachineSalt(saltFilePath)).update("\0").update(value).digest("hex").slice(0, 16);
1269
+ }
1270
+ }
1271
+ });
1272
+
1273
+ // ../packages/tool-kit/out/workContext.js
1274
+ var require_workContext = __commonJS({
1275
+ "../packages/tool-kit/out/workContext.js"(exports) {
1276
+ "use strict";
1277
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
1278
+ if (k2 === void 0) k2 = k;
1279
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1280
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1281
+ desc = { enumerable: true, get: function() {
1282
+ return m[k];
1283
+ } };
1284
+ }
1285
+ Object.defineProperty(o, k2, desc);
1286
+ } : function(o, m, k, k2) {
1287
+ if (k2 === void 0) k2 = k;
1288
+ o[k2] = m[k];
1289
+ });
1290
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
1291
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1292
+ } : function(o, v) {
1293
+ o["default"] = v;
1294
+ });
1295
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
1296
+ var ownKeys = function(o) {
1297
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1298
+ var ar = [];
1299
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1300
+ return ar;
1301
+ };
1302
+ return ownKeys(o);
1303
+ };
1304
+ return function(mod) {
1305
+ if (mod && mod.__esModule) return mod;
1306
+ var result = {};
1307
+ if (mod != null) {
1308
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1309
+ }
1310
+ __setModuleDefault(result, mod);
1311
+ return result;
1312
+ };
1313
+ }();
1314
+ Object.defineProperty(exports, "__esModule", { value: true });
1315
+ exports.deriveWorkContext = deriveWorkContext;
1316
+ var fs = __importStar(__require("fs"));
1317
+ var path = __importStar(__require("path"));
1318
+ var salt_1 = require_salt();
1319
+ var MAX_WALK_DEPTH = 64;
1320
+ function deriveWorkContext(cwd, saltFilePath) {
1321
+ if (!cwd || !cwd.trim())
1322
+ return null;
1323
+ const startPath = stripTrailingSeparators(cwd.trim());
1324
+ let roots = null;
1325
+ try {
1326
+ roots = resolveRepositoryRoots(startPath);
1327
+ } catch {
1328
+ roots = null;
1329
+ }
1330
+ const workspacePath = roots?.checkoutRoot ?? startPath;
1331
+ const workspaceLabel = basenameOf(workspacePath);
1332
+ if (!workspaceLabel)
1333
+ return null;
1334
+ const projectPath = roots?.canonicalRoot ?? null;
1335
+ const projectLabel = (projectPath ? basenameOf(projectPath) : null) ?? workspaceLabel;
1336
+ return {
1337
+ workspaceLabel,
1338
+ projectLabel,
1339
+ workspaceHash: (0, salt_1.hashWithMachineSalt)(workspaceLabel, saltFilePath),
1340
+ projectHash: (0, salt_1.hashWithMachineSalt)(projectLabel, saltFilePath),
1341
+ workspacePath,
1342
+ projectPath
1343
+ };
1344
+ }
1345
+ function resolveRepositoryRoots(startDir) {
1346
+ if (!fs.existsSync(startDir))
1347
+ return null;
1348
+ let dir = startDir;
1349
+ for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
1350
+ const dotGit = path.join(dir, ".git");
1351
+ let stat = null;
1352
+ try {
1353
+ stat = fs.statSync(dotGit);
1354
+ } catch {
1355
+ stat = null;
1356
+ }
1357
+ if (stat?.isDirectory())
1358
+ return { checkoutRoot: dir, canonicalRoot: dir };
1359
+ if (stat?.isFile())
1360
+ return { checkoutRoot: dir, canonicalRoot: worktreeParentRoot(dotGit, dir) ?? dir };
1361
+ const parent = path.dirname(dir);
1362
+ if (parent === dir)
1363
+ return null;
1364
+ dir = parent;
1365
+ }
1366
+ return null;
1367
+ }
1368
+ function worktreeParentRoot(dotGitFile, containingDir) {
1369
+ let gitdir;
1370
+ try {
1371
+ const match = /^gitdir:\s*(.+)\s*$/m.exec(fs.readFileSync(dotGitFile, "utf8"));
1372
+ if (!match)
1373
+ return null;
1374
+ gitdir = match[1].trim();
1375
+ } catch {
1376
+ return null;
1377
+ }
1378
+ const resolved = path.resolve(containingDir, gitdir);
1379
+ const marker = `${path.sep}.git${path.sep}worktrees${path.sep}`;
1380
+ const idx = resolved.indexOf(marker);
1381
+ if (idx === -1)
1382
+ return null;
1383
+ return resolved.slice(0, idx);
1384
+ }
1385
+ function stripTrailingSeparators(value) {
1386
+ let end = value.length;
1387
+ while (end > 1 && (value[end - 1] === "/" || value[end - 1] === "\\"))
1388
+ end--;
1389
+ return value.slice(0, end);
1390
+ }
1391
+ function basenameOf(value) {
1392
+ const segment = value.split(/[\\/]/).filter(Boolean).pop() ?? null;
1393
+ return segment && segment.length > 0 ? segment : null;
1394
+ }
1395
+ }
1396
+ });
1397
+
1024
1398
  // ../packages/tool-kit/out/hookAdapter.js
1025
1399
  var require_hookAdapter = __commonJS({
1026
1400
  "../packages/tool-kit/out/hookAdapter.js"(exports) {
1027
1401
  "use strict";
1028
1402
  Object.defineProperty(exports, "__esModule", { value: true });
1029
1403
  exports.DEFAULT_API_BASE_URL = void 0;
1404
+ exports.resolveContextHashes = resolveContextHashes;
1030
1405
  exports.loadCliAgentConfig = loadCliAgentConfig;
1031
1406
  exports.deliverHookEvents = deliverHookEvents;
1407
+ var contextRegistry_1 = require_contextRegistry();
1032
1408
  var eventLog_1 = require_eventLog();
1033
1409
  var eventSender_1 = require_eventSender();
1034
1410
  var tokenStore_1 = require_tokenStore();
1411
+ var workContext_1 = require_workContext();
1035
1412
  exports.DEFAULT_API_BASE_URL = "https://api.ascenda.one";
1036
- function loadCliAgentConfig(toolType, sessionIdFromHook) {
1413
+ function resolveContextHashes(cwd) {
1414
+ const workspaceOverride = process.env.ASCENDA_WORKSPACE_HASH?.trim() || null;
1415
+ const projectOverride = process.env.ASCENDA_PROJECT_HASH?.trim() || null;
1416
+ if (workspaceOverride && projectOverride)
1417
+ return { workspaceHash: workspaceOverride, projectHash: projectOverride };
1418
+ const context = (0, workContext_1.deriveWorkContext)(cwd ?? process.cwd());
1419
+ if (context)
1420
+ (0, contextRegistry_1.recordWorkContext)(context);
1421
+ return {
1422
+ workspaceHash: workspaceOverride ?? context?.workspaceHash ?? null,
1423
+ projectHash: projectOverride ?? context?.projectHash ?? null
1424
+ };
1425
+ }
1426
+ function loadCliAgentConfig(toolType, sessionIdFromHook, cwd) {
1037
1427
  const apiBaseUrl = (process.env.ASCENDA_API_BASE_URL ?? exports.DEFAULT_API_BASE_URL).replace(/\/$/, "");
1038
1428
  const toolInstallationIdRaw = process.env.ASCENDA_TOOL_INSTALLATION_ID;
1039
1429
  if (!toolInstallationIdRaw)
@@ -1046,13 +1436,15 @@ var require_hookAdapter = __commonJS({
1046
1436
  throw new Error("Missing ASCENDA_EVENT_WRITE_TOKEN (or token file)");
1047
1437
  if (!fileToken)
1048
1438
  (0, tokenStore_1.persistEventWriteToken)(tokenFilePath, eventWriteToken);
1439
+ const contextHashes = resolveContextHashes(cwd);
1049
1440
  return {
1050
1441
  apiBaseUrl,
1051
1442
  toolInstallationId,
1052
1443
  eventWriteToken,
1053
1444
  tokenFilePath,
1054
1445
  sessionId: process.env.ASCENDA_SESSION_ID ?? sessionIdFromHook ?? null,
1055
- workspaceHash: process.env.ASCENDA_WORKSPACE_HASH ?? null,
1446
+ workspaceHash: contextHashes.workspaceHash,
1447
+ projectHash: contextHashes.projectHash,
1056
1448
  // Agents await command hooks; fail fast rather than stall the user's turn.
1057
1449
  timeoutMs: parsePositiveInt(process.env.ASCENDA_HTTP_TIMEOUT_MS) ?? 3e3
1058
1450
  };
@@ -1063,11 +1455,12 @@ var require_hookAdapter = __commonJS({
1063
1455
  const notice = options.onNotice ?? ((message) => console.error(message));
1064
1456
  let config;
1065
1457
  try {
1066
- config = loadCliAgentConfig(options.toolType, options.sessionId);
1458
+ config = loadCliAgentConfig(options.toolType, options.sessionId, options.cwd);
1067
1459
  } catch (error) {
1068
1460
  const logFile = (0, eventLog_1.resolveEventLogPath)();
1069
1461
  if (!logFile)
1070
1462
  throw error;
1463
+ const contextHashes = resolveContextHashes(options.cwd);
1071
1464
  for (const event of events) {
1072
1465
  (0, eventLog_1.appendEventLog)(logFile, {
1073
1466
  loggedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1076,7 +1469,8 @@ var require_hookAdapter = __commonJS({
1076
1469
  toolInstallationId: `${options.toolType}:unpaired`,
1077
1470
  source: options.source,
1078
1471
  sessionId: options.sessionId ?? null,
1079
- workspaceHash: process.env.ASCENDA_WORKSPACE_HASH ?? null
1472
+ workspaceHash: contextHashes.workspaceHash,
1473
+ projectHash: contextHashes.projectHash
1080
1474
  }, event)
1081
1475
  });
1082
1476
  }
@@ -1090,6 +1484,7 @@ var require_hookAdapter = __commonJS({
1090
1484
  tokenFilePath: config.tokenFilePath,
1091
1485
  sessionId: config.sessionId,
1092
1486
  workspaceHash: config.workspaceHash,
1487
+ projectHash: config.projectHash,
1093
1488
  timeoutMs: config.timeoutMs
1094
1489
  });
1095
1490
  for (const event of events) {
@@ -1195,89 +1590,6 @@ var require_turnState = __commonJS({
1195
1590
  }
1196
1591
  });
1197
1592
 
1198
- // ../packages/tool-kit/out/salt.js
1199
- var require_salt = __commonJS({
1200
- "../packages/tool-kit/out/salt.js"(exports) {
1201
- "use strict";
1202
- var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
1203
- if (k2 === void 0) k2 = k;
1204
- var desc = Object.getOwnPropertyDescriptor(m, k);
1205
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1206
- desc = { enumerable: true, get: function() {
1207
- return m[k];
1208
- } };
1209
- }
1210
- Object.defineProperty(o, k2, desc);
1211
- } : function(o, m, k, k2) {
1212
- if (k2 === void 0) k2 = k;
1213
- o[k2] = m[k];
1214
- });
1215
- var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
1216
- Object.defineProperty(o, "default", { enumerable: true, value: v });
1217
- } : function(o, v) {
1218
- o["default"] = v;
1219
- });
1220
- var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
1221
- var ownKeys = function(o) {
1222
- ownKeys = Object.getOwnPropertyNames || function(o2) {
1223
- var ar = [];
1224
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1225
- return ar;
1226
- };
1227
- return ownKeys(o);
1228
- };
1229
- return function(mod) {
1230
- if (mod && mod.__esModule) return mod;
1231
- var result = {};
1232
- if (mod != null) {
1233
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1234
- }
1235
- __setModuleDefault(result, mod);
1236
- return result;
1237
- };
1238
- }();
1239
- Object.defineProperty(exports, "__esModule", { value: true });
1240
- exports.machineSaltFilePath = machineSaltFilePath;
1241
- exports.readOrCreateMachineSalt = readOrCreateMachineSalt;
1242
- exports.hashWithMachineSalt = hashWithMachineSalt;
1243
- var crypto = __importStar(__require("crypto"));
1244
- var fs = __importStar(__require("fs"));
1245
- var os = __importStar(__require("os"));
1246
- var path = __importStar(__require("path"));
1247
- function machineSaltFilePath() {
1248
- return path.join(os.homedir(), ".ascenda", "salt");
1249
- }
1250
- var cache = /* @__PURE__ */ new Map();
1251
- function readOrCreateMachineSalt(saltFilePath = machineSaltFilePath()) {
1252
- const hit = cache.get(saltFilePath);
1253
- if (hit)
1254
- return hit;
1255
- const dir = path.dirname(saltFilePath);
1256
- fs.mkdirSync(dir, { recursive: true, mode: 448 });
1257
- let salt;
1258
- try {
1259
- salt = crypto.randomBytes(32).toString("hex");
1260
- fs.writeFileSync(saltFilePath, salt, { encoding: "utf8", mode: 384, flag: "wx" });
1261
- } catch (error) {
1262
- if (error.code !== "EEXIST")
1263
- throw error;
1264
- salt = fs.readFileSync(saltFilePath, "utf8").trim();
1265
- }
1266
- if (process.platform !== "win32") {
1267
- fs.chmodSync(dir, 448);
1268
- fs.chmodSync(saltFilePath, 384);
1269
- }
1270
- cache.set(saltFilePath, salt);
1271
- return salt;
1272
- }
1273
- function hashWithMachineSalt(value, saltFilePath) {
1274
- if (!value)
1275
- return null;
1276
- return crypto.createHash("sha256").update(readOrCreateMachineSalt(saltFilePath)).update("\0").update(value).digest("hex").slice(0, 16);
1277
- }
1278
- }
1279
- });
1280
-
1281
1593
  // ../packages/tool-kit/out/liveBus.js
1282
1594
  var require_liveBus = __commonJS({
1283
1595
  "../packages/tool-kit/out/liveBus.js"(exports) {
@@ -1330,6 +1642,7 @@ var require_liveBus = __commonJS({
1330
1642
  var path = __importStar(__require("path"));
1331
1643
  var WRITE_TIMEOUT_MS = 50;
1332
1644
  var APP_BUNDLE_ID = "one.ascenda.ascendaMissionControl";
1645
+ var SAVER_HOST_BUNDLE_ID = "com.apple.ScreenSaver.Engine.legacyScreenSaver";
1333
1646
  function liveBusSocketCandidates() {
1334
1647
  const override = process.env.ASCENDA_LIVE_BUS_SOCKET;
1335
1648
  if (override)
@@ -1337,7 +1650,8 @@ var require_liveBus = __commonJS({
1337
1650
  const home = os.homedir();
1338
1651
  return [
1339
1652
  path.join(home, ".ascenda", "live.sock"),
1340
- path.join(home, "Library", "Containers", APP_BUNDLE_ID, "Data", ".ascenda", "live.sock")
1653
+ path.join(home, "Library", "Containers", APP_BUNDLE_ID, "Data", ".ascenda", "live.sock"),
1654
+ path.join(home, "Library", "Containers", SAVER_HOST_BUNDLE_ID, "Data", "l.sock")
1341
1655
  ];
1342
1656
  }
1343
1657
  function liveBusSocketPath() {
@@ -1409,8 +1723,8 @@ var require_out2 = __commonJS({
1409
1723
  "../packages/tool-kit/out/index.js"(exports) {
1410
1724
  "use strict";
1411
1725
  Object.defineProperty(exports, "__esModule", { value: true });
1412
- exports.renewToolToken = exports.getPairingStatus = exports.createPairingSession = exports.AscendaApiError = exports.liveBusSocketCandidates = exports.liveBusSocketPath = exports.bucketPromptSize = exports.emitLiveSignal = exports.hashWithMachineSalt = exports.readOrCreateMachineSalt = exports.machineSaltFilePath = exports.markFailureNotified = exports.shouldAnnounceFailure = exports.recordSendOutcome = exports.readCollectorState = exports.defaultStateFilePath = exports.readTokenFile = exports.persistEventWriteToken = exports.defaultTokenFilePath = exports.recordTurnStart = exports.consumeTurnDurationMs = exports.loadCliAgentConfig = exports.deliverHookEvents = exports.DEFAULT_API_BASE_URL = exports.resolveEventLogPath = exports.expandUserPath = exports.appendEventLog = exports.EVENT_LOG_ENV_VAR = exports.buildEventPayload = exports.AscendaSemanticEventError = exports.AscendaEventSender = exports.looksLikeCorrection = exports.outcomeForHook = exports.inferOutcome = exports.getNestedNumber = exports.getNestedString = exports.getNested = exports.getNumber = exports.getString = exports.localHourAt = exports.utcOffsetMinutesAt = exports.isAfterHours = exports.bucketDurationMs = exports.bucketLinesChanged = exports.invitesDebrief = exports.classifyWorkMilestone = exports.isReworkGitAction = exports.classifyGitAction = exports.isVerificationCommand = exports.classifyCommand = void 0;
1413
- exports.isRetryableStatus = exports.parseIngestResponse = exports.postToolEventsBatch = exports.postToolEvent = void 0;
1726
+ exports.workContextRegistryFilePath = exports.readWorkContextRegistry = exports.recordWorkContextAlias = exports.recordWorkContext = exports.deriveWorkContext = exports.hashWithMachineSalt = exports.readOrCreateMachineSalt = exports.machineSaltFilePath = exports.markFailureNotified = exports.shouldAnnounceFailure = exports.recordSendOutcome = exports.readCollectorState = exports.defaultStateFilePath = exports.readTokenFile = exports.persistEventWriteToken = exports.defaultTokenFilePath = exports.recordTurnStart = exports.consumeTurnDurationMs = exports.resolveContextHashes = exports.loadCliAgentConfig = exports.deliverHookEvents = exports.DEFAULT_API_BASE_URL = exports.resolveEventLogPath = exports.expandUserPath = exports.appendEventLog = exports.EVENT_LOG_ENV_VAR = exports.buildEventPayload = exports.AscendaSemanticEventError = exports.AscendaEventSender = exports.looksLikeCorrection = exports.outcomeForHook = exports.inferOutcome = exports.getNestedNumber = exports.getNestedString = exports.getNested = exports.getNumber = exports.getString = exports.localHourAt = exports.utcOffsetMinutesAt = exports.BUSINESS_DAY = exports.isOutsideBusinessHours = exports.isAfterHours = exports.bucketDurationMs = exports.bucketLinesChanged = exports.invitesDebrief = exports.classifyWorkMilestone = exports.isReworkGitAction = exports.classifyGitAction = exports.isVerificationCommand = exports.classifyCommand = void 0;
1727
+ exports.isRetryableStatus = exports.parseIngestResponse = exports.postToolEventsBatch = exports.postToolEvent = exports.renewToolToken = exports.getPairingStatus = exports.createPairingSession = exports.AscendaApiError = exports.liveBusSocketCandidates = exports.liveBusSocketPath = exports.bucketPromptSize = exports.emitLiveSignal = void 0;
1414
1728
  var commandClassifier_1 = require_commandClassifier();
1415
1729
  Object.defineProperty(exports, "classifyCommand", { enumerable: true, get: function() {
1416
1730
  return commandClassifier_1.classifyCommand;
@@ -1443,6 +1757,12 @@ var require_out2 = __commonJS({
1443
1757
  Object.defineProperty(exports, "isAfterHours", { enumerable: true, get: function() {
1444
1758
  return afterHours_1.isAfterHours;
1445
1759
  } });
1760
+ Object.defineProperty(exports, "isOutsideBusinessHours", { enumerable: true, get: function() {
1761
+ return afterHours_1.isOutsideBusinessHours;
1762
+ } });
1763
+ Object.defineProperty(exports, "BUSINESS_DAY", { enumerable: true, get: function() {
1764
+ return afterHours_1.BUSINESS_DAY;
1765
+ } });
1446
1766
  Object.defineProperty(exports, "utcOffsetMinutesAt", { enumerable: true, get: function() {
1447
1767
  return afterHours_1.utcOffsetMinutesAt;
1448
1768
  } });
@@ -1507,6 +1827,9 @@ var require_out2 = __commonJS({
1507
1827
  Object.defineProperty(exports, "loadCliAgentConfig", { enumerable: true, get: function() {
1508
1828
  return hookAdapter_1.loadCliAgentConfig;
1509
1829
  } });
1830
+ Object.defineProperty(exports, "resolveContextHashes", { enumerable: true, get: function() {
1831
+ return hookAdapter_1.resolveContextHashes;
1832
+ } });
1510
1833
  var turnState_1 = require_turnState();
1511
1834
  Object.defineProperty(exports, "consumeTurnDurationMs", { enumerable: true, get: function() {
1512
1835
  return turnState_1.consumeTurnDurationMs;
@@ -1550,6 +1873,23 @@ var require_out2 = __commonJS({
1550
1873
  Object.defineProperty(exports, "hashWithMachineSalt", { enumerable: true, get: function() {
1551
1874
  return salt_1.hashWithMachineSalt;
1552
1875
  } });
1876
+ var workContext_1 = require_workContext();
1877
+ Object.defineProperty(exports, "deriveWorkContext", { enumerable: true, get: function() {
1878
+ return workContext_1.deriveWorkContext;
1879
+ } });
1880
+ var contextRegistry_1 = require_contextRegistry();
1881
+ Object.defineProperty(exports, "recordWorkContext", { enumerable: true, get: function() {
1882
+ return contextRegistry_1.recordWorkContext;
1883
+ } });
1884
+ Object.defineProperty(exports, "recordWorkContextAlias", { enumerable: true, get: function() {
1885
+ return contextRegistry_1.recordWorkContextAlias;
1886
+ } });
1887
+ Object.defineProperty(exports, "readWorkContextRegistry", { enumerable: true, get: function() {
1888
+ return contextRegistry_1.readWorkContextRegistry;
1889
+ } });
1890
+ Object.defineProperty(exports, "workContextRegistryFilePath", { enumerable: true, get: function() {
1891
+ return contextRegistry_1.workContextRegistryFilePath;
1892
+ } });
1553
1893
  var liveBus_1 = require_liveBus();
1554
1894
  Object.defineProperty(exports, "emitLiveSignal", { enumerable: true, get: function() {
1555
1895
  return liveBus_1.emitLiveSignal;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "publishConfig": { "access": "public" },
3
3
  "name": "@ascenda-one/github-collector",
4
- "version": "0.1.12",
4
+ "version": "0.1.14",
5
5
  "description": "Code-forge collaboration collector for Ascenda work telemetry — first-person review and pull-request signals.",
6
6
  "repository": {
7
7
  "type": "git",