@ascenda-one/github-collector 0.1.13 → 0.1.15

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 +164 -5
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -377,12 +377,155 @@ var require_payload = __commonJS({
377
377
  }
378
378
  });
379
379
 
380
+ // ../packages/tool-contract/out/metricKeys.js
381
+ var require_metricKeys = __commonJS({
382
+ "../packages/tool-contract/out/metricKeys.js"(exports) {
383
+ "use strict";
384
+ Object.defineProperty(exports, "__esModule", { value: true });
385
+ exports.METRIC_KEYS = void 0;
386
+ exports.backendMetricKeys = backendMetricKeys;
387
+ var CONTEXT_WINDOW_CANONICAL_ALIASES = [
388
+ "contextWindowPeakPct",
389
+ "context_window_peak_pct",
390
+ "contextWindowPct",
391
+ "context_window_pct"
392
+ ];
393
+ var CONTEXT_WINDOW_CURSOR_PERCENT_ALIASES = ["contextUsagePercent"];
394
+ exports.METRIC_KEYS = {
395
+ // ── Read by a backend reader ────────────────────────────────────────────
396
+ contextWindowPeakPct: {
397
+ readBy: ["backend", "handoff"],
398
+ backendAliases: CONTEXT_WINDOW_CANONICAL_ALIASES,
399
+ unit: "fraction of the context window (0\u20131; uncapped for >200k contexts)",
400
+ note: "Claude Code reports a true per-session peak. Cursor reports its composer's last known occupancy under the same key \u2014 the closest its store can answer, and not the same measurement."
401
+ },
402
+ contextUsagePercent: {
403
+ readBy: ["backend", "handoff"],
404
+ backendAliases: CONTEXT_WINDOW_CURSOR_PERCENT_ALIASES,
405
+ unit: "percent (0\u2013100)",
406
+ note: "Cursor's own column name. Superseded by contextWindowPeakPct on the wire; kept because the handoff reads it and imported rows carry it. Unit-explicit on the backend: always divided by 100, never put through the fraction-or-percent heuristic."
407
+ },
408
+ promptCount: { readBy: ["backend", "handoff"], backendAliases: ["promptCount", "prompt_count"] },
409
+ sessionMinutes: { readBy: ["backend"], backendAliases: ["sessionMinutes", "session_minutes"], unit: "minutes" },
410
+ durationBucket: { readBy: ["backend", "handoff"], backendAliases: ["durationBucket", "duration_bucket"] },
411
+ afterHoursPrompts: { readBy: ["backend", "handoff"], backendAliases: ["afterHoursPrompts", "after_hours_prompts"] },
412
+ inputTokens: { readBy: ["backend"], backendAliases: ["inputTokens", "input_tokens"], unit: "tokens" },
413
+ outputTokens: { readBy: ["backend"], backendAliases: ["outputTokens", "output_tokens"], unit: "tokens" },
414
+ cacheReadTokens: { readBy: ["backend"], backendAliases: ["cacheReadTokens", "cache_read_tokens"], unit: "tokens" },
415
+ queuedPrompts: { readBy: ["backend"], backendAliases: ["queuedPrompts", "queued_prompts"] },
416
+ linesChangedBucket: { readBy: ["backend"], backendAliases: ["linesChangedBucket", "lines_changed_bucket"] },
417
+ // ── Read by the local handoff only ──────────────────────────────────────
418
+ activeMinutes: { readBy: ["handoff"], unit: "minutes" },
419
+ afterHoursRequests: { readBy: ["handoff"] },
420
+ approximateLintErrorsCount: { readBy: ["handoff"] },
421
+ canceledCount: { readBy: ["handoff"] },
422
+ chatEditCount: { readBy: ["handoff"] },
423
+ compactionCount: {
424
+ readBy: ["handoff"],
425
+ note: "The backend counts context_compression_* event rows, not this key. Both are emitted; this one is for the handoff."
426
+ },
427
+ contextWindowPeakTokens: {
428
+ readBy: ["handoff"],
429
+ unit: "tokens",
430
+ note: "The measured quantity, with no assumed denominator. Prefer this to the ratio for any within-person baseline."
431
+ },
432
+ date: { readBy: ["handoff"] },
433
+ errorCount: { readBy: ["handoff"] },
434
+ filesChangedCount: { readBy: ["handoff"] },
435
+ humanChangesCount: { readBy: ["handoff"] },
436
+ linesAdded: { readBy: ["handoff"] },
437
+ linesRemoved: { readBy: ["handoff"] },
438
+ primaryModel: { readBy: ["handoff"] },
439
+ requestCount: { readBy: ["handoff"] },
440
+ sessionStartedAt: { readBy: ["handoff"] },
441
+ subagentComposers: { readBy: ["handoff"] },
442
+ subagentToolCallCount: {
443
+ readBy: ["handoff"],
444
+ note: "Claude Code only: calls made inside subagent transcripts, kept out of toolCallCount so the main-loop count matches what the wire events carry."
445
+ },
446
+ subagentTranscripts: { readBy: ["handoff"] },
447
+ toolCallCount: {
448
+ readBy: ["handoff"],
449
+ note: "The backend counts ai_tool_call_started event rows, not this key \u2014 same split as compactionCount. Deduplicated on the tool-call id; see each extractor for what one call means in its store."
450
+ },
451
+ toolCallsUndated: {
452
+ readBy: ["handoff"],
453
+ note: "Cursor only: calls whose every record carries an empty createdAt. Counted in toolCallCount, but no event exists for them \u2014 the wire total is smaller than this session count by exactly this number."
454
+ },
455
+ toolFailureCount: { readBy: ["handoff"] },
456
+ totalEntryCount: { readBy: ["handoff"] },
457
+ userModifiedEditCount: {
458
+ readBy: ["handoff"],
459
+ note: "Null, never 0 \u2014 Claude Code never sets userModified true, so 0 would assert 'no AI edit was ever corrected by hand'."
460
+ },
461
+ // ── Diagnostic: read by nobody, on purpose ──────────────────────────────
462
+ abandonedPromptCount: { readBy: ["diagnostic"] },
463
+ // Epoch-marker metrics. The marker is local-only and never reaches the wire
464
+ // (see EXTRACTION_EPOCH_KIND), but it travels as a NormalizedHistoricalEvent
465
+ // and so is keyed by the same vocabulary.
466
+ windowOldest: { readBy: ["handoff"], note: "Oldest event the extraction saw \u2014 the marker's left edge." },
467
+ windowNewest: { readBy: ["handoff"], note: "Newest event the extraction saw \u2014 the marker's right edge." },
468
+ projectsWithNoReadableTranscript: { readBy: ["diagnostic"] },
469
+ unparsedComposerHeaders: { readBy: ["diagnostic"] },
470
+ unknownComposerHeaderTypes: { readBy: ["diagnostic"] },
471
+ orphanedBubbles: { readBy: ["diagnostic"] },
472
+ orphanedSubagentBubbles: { readBy: ["diagnostic"] },
473
+ sessionsWithoutTimeline: { readBy: ["diagnostic"] },
474
+ emptyComposers: { readBy: ["diagnostic"] },
475
+ apiErrorCount: { readBy: ["diagnostic"] },
476
+ assistantTurns: { readBy: ["diagnostic"] },
477
+ compactionAutoCount: { readBy: ["diagnostic"] },
478
+ compactionManualCount: { readBy: ["diagnostic"] },
479
+ editDayCount: { readBy: ["diagnostic"] },
480
+ emptyChatSessions: { readBy: ["diagnostic"] },
481
+ gitBranch: { readBy: ["diagnostic"] },
482
+ linesChanged: { readBy: ["diagnostic"] },
483
+ malformedChatSessionLines: { readBy: ["diagnostic"] },
484
+ malformedHistoryEntries: { readBy: ["diagnostic"] },
485
+ mode: { readBy: ["diagnostic"] },
486
+ modelCount: { readBy: ["diagnostic"] },
487
+ modelSwitchCount: { readBy: ["diagnostic"] },
488
+ rapidRepromptCount: { readBy: ["diagnostic"] },
489
+ schemaUnreadable: { readBy: ["diagnostic"] },
490
+ sessionCount: { readBy: ["diagnostic"] },
491
+ sessionsFromBubbleTimeline: { readBy: ["diagnostic"] },
492
+ sessionsFromCheckpointTimeline: { readBy: ["diagnostic"] },
493
+ sessionsFromRecencyTimeline: { readBy: ["diagnostic"] },
494
+ subagentAssistantTurns: { readBy: ["diagnostic"] },
495
+ subagentPrompts: { readBy: ["diagnostic"] },
496
+ subagentTokensTotal: { readBy: ["diagnostic"] },
497
+ toolName: {
498
+ readBy: ["diagnostic"],
499
+ note: "Set per ai_tool_call_started event by #43's extractors and shipped in wire metadata, but no reader resolves it server-side yet (the backend's ToolName column is MCP audit, not telemetry). Registered after the fact: #38 and #43 merged past each other, and the union caught it on the next compile \u2014 metaLines all over again."
500
+ },
501
+ toolResultCount: { readBy: ["diagnostic"] },
502
+ toolResultErrorCount: { readBy: ["diagnostic"] },
503
+ unknownBubbles: { readBy: ["diagnostic"] },
504
+ unknownLines: { readBy: ["diagnostic"] },
505
+ metaLines: {
506
+ readBy: ["diagnostic"],
507
+ note: 'Recognised-but-skipped transcript machinery (file-history-snapshot, queued-command, \u2026). Split out of unknownLines by #43 so that number keeps meaning "a type nobody has looked at". Registered here after the fact: #41 and #43 merged past each other, and the union caught it on the next compile \u2014 which is this module doing its job.'
508
+ },
509
+ unparsedBubbles: { readBy: ["diagnostic"] },
510
+ unparsedChatSessionFiles: { readBy: ["diagnostic"] },
511
+ unparsedHistoryFiles: { readBy: ["diagnostic"] },
512
+ unparsedLines: { readBy: ["diagnostic"] },
513
+ unreadableChatSessionFiles: { readBy: ["diagnostic"] },
514
+ unreadableHistoryFiles: { readBy: ["diagnostic"] },
515
+ unrecognisedChatSessionFiles: { readBy: ["diagnostic"] }
516
+ };
517
+ function backendMetricKeys() {
518
+ return Object.entries(exports.METRIC_KEYS).filter(([, spec]) => spec.readBy.includes("backend")).map(([key, spec]) => [key, spec.backendAliases ?? [key]]);
519
+ }
520
+ }
521
+ });
522
+
380
523
  // ../packages/tool-contract/out/index.js
381
524
  var require_out = __commonJS({
382
525
  "../packages/tool-contract/out/index.js"(exports) {
383
526
  "use strict";
384
527
  Object.defineProperty(exports, "__esModule", { value: true });
385
- exports.ASCENDA_SEMANTIC_PROVENANCE = exports.ASCENDA_HISTORICAL_CONSENT_SCOPE = exports.ASCENDA_COLLABORATION_CONSENT_SCOPE = exports.ASCENDA_SEMANTIC_CONSENT_SCOPE = exports.ASCENDA_PROVENANCE = exports.ASCENDA_CONSENT_SCOPE = exports.EVENT_WORKLOAD_CATEGORY = exports.COLLABORATION_EVENT_TYPES = exports.SEMANTIC_WORK_SIGNAL_EVENT_TYPES = void 0;
528
+ exports.backendMetricKeys = exports.METRIC_KEYS = exports.ASCENDA_SEMANTIC_PROVENANCE = exports.ASCENDA_HISTORICAL_CONSENT_SCOPE = exports.ASCENDA_COLLABORATION_CONSENT_SCOPE = exports.ASCENDA_SEMANTIC_CONSENT_SCOPE = exports.ASCENDA_PROVENANCE = exports.ASCENDA_CONSENT_SCOPE = exports.EVENT_WORKLOAD_CATEGORY = exports.COLLABORATION_EVENT_TYPES = exports.SEMANTIC_WORK_SIGNAL_EVENT_TYPES = void 0;
386
529
  exports.SEMANTIC_WORK_SIGNAL_EVENT_TYPES = [
387
530
  "approach_churn_detected",
388
531
  "goal_drift_detected",
@@ -441,6 +584,13 @@ var require_out = __commonJS({
441
584
  exports.ASCENDA_COLLABORATION_CONSENT_SCOPE = "workflow_telemetry";
442
585
  exports.ASCENDA_HISTORICAL_CONSENT_SCOPE = "historical_import";
443
586
  exports.ASCENDA_SEMANTIC_PROVENANCE = "semantic_work_signals";
587
+ var metricKeys_1 = require_metricKeys();
588
+ Object.defineProperty(exports, "METRIC_KEYS", { enumerable: true, get: function() {
589
+ return metricKeys_1.METRIC_KEYS;
590
+ } });
591
+ Object.defineProperty(exports, "backendMetricKeys", { enumerable: true, get: function() {
592
+ return metricKeys_1.backendMetricKeys;
593
+ } });
444
594
  }
445
595
  });
446
596
 
@@ -675,6 +825,7 @@ var require_tokenStore = __commonJS({
675
825
  };
676
826
  }();
677
827
  Object.defineProperty(exports, "__esModule", { value: true });
828
+ exports.ascendaHome = ascendaHome;
678
829
  exports.defaultTokenFilePath = defaultTokenFilePath2;
679
830
  exports.persistEventWriteToken = persistEventWriteToken2;
680
831
  exports.readTokenFile = readTokenFile2;
@@ -682,8 +833,11 @@ var require_tokenStore = __commonJS({
682
833
  var fs = __importStar(__require("fs"));
683
834
  var os = __importStar(__require("os"));
684
835
  var path = __importStar(__require("path"));
836
+ function ascendaHome() {
837
+ return process.env.ASCENDA_HOME ?? path.join(os.homedir(), ".ascenda");
838
+ }
685
839
  function defaultTokenFilePath2(toolInstallationId) {
686
- return path.join(os.homedir(), ".ascenda", "tokens", sanitizeFilePart(toolInstallationId));
840
+ return path.join(ascendaHome(), "tokens", sanitizeFilePart(toolInstallationId));
687
841
  }
688
842
  function persistEventWriteToken2(tokenFilePath, token) {
689
843
  const dir = path.dirname(tokenFilePath);
@@ -1642,6 +1796,7 @@ var require_liveBus = __commonJS({
1642
1796
  var path = __importStar(__require("path"));
1643
1797
  var WRITE_TIMEOUT_MS = 50;
1644
1798
  var APP_BUNDLE_ID = "one.ascenda.ascendaMissionControl";
1799
+ var SAVER_HOST_BUNDLE_ID = "com.apple.ScreenSaver.Engine.legacyScreenSaver";
1645
1800
  function liveBusSocketCandidates() {
1646
1801
  const override = process.env.ASCENDA_LIVE_BUS_SOCKET;
1647
1802
  if (override)
@@ -1649,7 +1804,8 @@ var require_liveBus = __commonJS({
1649
1804
  const home = os.homedir();
1650
1805
  return [
1651
1806
  path.join(home, ".ascenda", "live.sock"),
1652
- path.join(home, "Library", "Containers", APP_BUNDLE_ID, "Data", ".ascenda", "live.sock")
1807
+ path.join(home, "Library", "Containers", APP_BUNDLE_ID, "Data", ".ascenda", "live.sock"),
1808
+ path.join(home, "Library", "Containers", SAVER_HOST_BUNDLE_ID, "Data", "l.sock")
1653
1809
  ];
1654
1810
  }
1655
1811
  function liveBusSocketPath() {
@@ -1721,8 +1877,8 @@ var require_out2 = __commonJS({
1721
1877
  "../packages/tool-kit/out/index.js"(exports) {
1722
1878
  "use strict";
1723
1879
  Object.defineProperty(exports, "__esModule", { value: true });
1724
- 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;
1725
- 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;
1880
+ 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.ascendaHome = 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;
1881
+ exports.isRetryableStatus = exports.parseIngestResponse = exports.postToolEventsBatch = exports.postToolEvent = exports.renewToolToken = exports.getPairingStatus = exports.createPairingSession = exports.AscendaApiError = exports.liveBusSocketCandidates = exports.liveBusSocketPath = exports.bucketPromptSize = exports.emitLiveSignal = exports.workContextRegistryFilePath = void 0;
1726
1882
  var commandClassifier_1 = require_commandClassifier();
1727
1883
  Object.defineProperty(exports, "classifyCommand", { enumerable: true, get: function() {
1728
1884
  return commandClassifier_1.classifyCommand;
@@ -1836,6 +1992,9 @@ var require_out2 = __commonJS({
1836
1992
  return turnState_1.recordTurnStart;
1837
1993
  } });
1838
1994
  var tokenStore_1 = require_tokenStore();
1995
+ Object.defineProperty(exports, "ascendaHome", { enumerable: true, get: function() {
1996
+ return tokenStore_1.ascendaHome;
1997
+ } });
1839
1998
  Object.defineProperty(exports, "defaultTokenFilePath", { enumerable: true, get: function() {
1840
1999
  return tokenStore_1.defaultTokenFilePath;
1841
2000
  } });
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.13",
4
+ "version": "0.1.15",
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",