@bli-cockpit/cli 0.2.293 → 0.2.294

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 (48) hide show
  1. package/dist/adapters/codex-attribution.js +28 -7
  2. package/dist/adapters/codex-segment-discovery.js +12 -3
  3. package/dist/adapters/codex-session-revision.js +58 -3
  4. package/dist/adapters/local-sources.js +1 -0
  5. package/dist/adapters/opencode-store.js +201 -0
  6. package/dist/adapters/raw-evidence-attribution-gaps.js +5 -0
  7. package/dist/adapters/raw-evidence-codex-reader.js +25 -3
  8. package/dist/adapters/raw-evidence-transcript-body.js +7 -2
  9. package/dist/adapters/raw-evidence-transcript-file.js +19 -0
  10. package/dist/adapters/raw-evidence-transcript-stream.js +6 -3
  11. package/dist/adapters/raw-evidence.js +13 -0
  12. package/dist/adapters/t3-projection-source.js +96 -0
  13. package/dist/commands/backfill-checkpoint.js +1 -1
  14. package/dist/commands/backfill-issues.js +5 -0
  15. package/dist/commands/backfill-output.js +6 -0
  16. package/dist/commands/backfill-report.js +3 -3
  17. package/dist/commands/backfill-scan.js +2 -0
  18. package/dist/commands/backfill-scope.js +2 -0
  19. package/dist/commands/backfill-upload.js +3 -2
  20. package/dist/commands/backfill.js +20 -3
  21. package/dist/commands/codex-revision-facts.js +3 -3
  22. package/dist/commands/collection-report.js +6 -0
  23. package/dist/commands/local-args-collector-status.js +2 -2
  24. package/dist/commands/local-args-collector-work.js +2 -2
  25. package/dist/commands/local-help-commands-tower.js +1 -1
  26. package/dist/commands/local-help.js +3 -3
  27. package/dist/commands/opencode-sync.js +163 -0
  28. package/dist/commands/public-root.js +1 -1
  29. package/dist/commands/session-sync-failures.js +4 -0
  30. package/dist/commands/session-sync-record.js +1 -1
  31. package/dist/commands/session-sync-upload.js +2 -1
  32. package/dist/commands/session-sync.js +18 -1
  33. package/dist/commands/sessions.js +27 -8
  34. package/dist/commands/sources-check.js +54 -47
  35. package/dist/commands/sources-discovery.js +35 -4
  36. package/dist/commands/sources-verdict.js +3 -3
  37. package/dist/local-state-status.js +18 -1
  38. package/dist/opencode-inventory.js +203 -0
  39. package/dist/opencode-policy.js +29 -0
  40. package/dist/slim/slim-transcript.js +3 -2
  41. package/dist/source-opt-out.js +2 -1
  42. package/dist/spool/local-spool-parse.js +1 -1
  43. package/dist/state-dir-audit.js +2 -0
  44. package/dist/sync-health-class.js +2 -0
  45. package/dist/upload-envelope-build.js +1 -0
  46. package/dist/upload-evidence-delivery-summary.js +10 -0
  47. package/dist/upload-session-reports-wire.js +15 -8
  48. package/package.json +4 -4
@@ -37,6 +37,8 @@ export const STUDIES_DIR_SUFFIX = "-studies";
37
37
  * collector name; none does today, and the test pins that.
38
38
  */
39
39
  export const STATE_DIR_RULES = [
40
+ { name: "opencode-transcripts", match: "exact", class: "state", bound: "redacted native reader derivatives; existing staging allowance and state ceiling govern every write; current derivatives removed after durable evidence and metadata acknowledgments" },
41
+ { name: "opencode-", match: "prefix", class: "state", bound: "native identity cursors and metadata-only coverage receipt; overwritten by collection" },
40
42
  { name: "raw-evidence", match: "exact", class: "staging", bound: "staged copies go the tick the server commits them; 256 MiB cap; the staging gate stops new copies at the cap, on a low disk or over the 512 MiB ceiling; uncommitted evidence is never deleted, only counted" },
41
43
  { name: "sync.log", match: "prefix", class: "logs", bound: "rotated every tick at 10 MiB, at most 2 archives (20 MB) per stream" },
42
44
  { name: "sync.err.log", match: "prefix", class: "logs", bound: "rotated every tick at 10 MiB, at most 2 archives (20 MB) per stream" },
@@ -68,6 +68,7 @@ export const SYNC_FAILURE_LABELS = [
68
68
  /** The session store itself could not be read during the scan. */
69
69
  "codex_scan_read_failed",
70
70
  "claude_scan_read_failed",
71
+ "opencode_scan_read_failed",
71
72
  /** Sessions were observed and their metadata report did not reach the door. */
72
73
  "session_report_unposted",
73
74
  /** The gate is real and this file forgot to say why — a bug, made visible. */
@@ -104,6 +105,7 @@ export const SYNC_FAILURE_LABEL_CLASSES = {
104
105
  claude_session_read_failed: "sync_failed",
105
106
  codex_scan_read_failed: "sync_failed",
106
107
  claude_scan_read_failed: "sync_failed",
108
+ opencode_scan_read_failed: "sync_failed",
107
109
  session_report_unposted: "sync_failed",
108
110
  sync_failed_reason_not_recorded: "sync_failed",
109
111
  };
@@ -164,6 +164,7 @@ async function collectEnvelopeSources(options, config, paths, repoRoot, uploadCo
164
164
  rawEvidenceIncludeClaudeJsonl: switches.claude ? options.rawEvidenceIncludeClaudeJsonl : false,
165
165
  rawEvidenceCodexSessionFiles: options.codexSessionFiles,
166
166
  rawEvidenceCodexAttributionScan: options.codexAttributionScan,
167
+ rawEvidenceNativeSessionFiles: options.nativeSessionFiles,
167
168
  rawEvidenceClaudeSessionFiles: options.claudeSessionFiles,
168
169
  rawEvidenceClaudeAttributionScan: options.claudeAttributionScan,
169
170
  rawEvidenceSkipContentHashes: reusableContentHashes(options, {
@@ -9,9 +9,12 @@ import { DELIVERY_BACKOFF_HOLDING_REASON, summarizeStuckEvidence, terminalDelive
9
9
  */
10
10
  export function retrySourcesForFailedSync(options, facts) {
11
11
  const sources = new Set();
12
+ if (options.nativeSessionFiles?.length)
13
+ sources.add("opencode");
12
14
  if ((options.codexSessionFiles?.length ?? 0) > 0 ||
13
15
  (options.codexAttributionScan?.directory_read_failed_count ?? 0) > 0 ||
14
16
  (options.codexAttributionScan?.stat_failed_count ?? 0) > 0 ||
17
+ Boolean(options.codexAttributionScan?.projection_failure_reason) ||
15
18
  facts?.evidence_completeness.source_counts.some((count) => count.source.startsWith("codex_") &&
16
19
  count.scanned_count + count.included_count + count.reused_count > 0)) {
17
20
  sources.add("codex");
@@ -99,9 +102,16 @@ export function hasRetryableEvidenceGap(facts, outcomes) {
99
102
  * Retryable and failed are separate questions: a hold remains missing evidence
100
103
  * without making the scheduled tick itself a failed attempt.
101
104
  */
105
+ const retryableT3ProjectionFailures = new Set([
106
+ "t3_projection_unreadable", "t3_projection_inventory_capped", "t3_projection_messages_capped",
107
+ "t3_projection_bytes_capped", "t3_projection_mapping_invalid",
108
+ "t3_native_identity_index_capped",
109
+ ]);
102
110
  function isRetryableEvidenceSkipReason(reason) {
103
111
  if (reason === DELIVERY_BACKOFF_HOLDING_REASON)
104
112
  return true;
113
+ if (retryableT3ProjectionFailures.has(reason))
114
+ return true;
105
115
  return /(?:read|stat|directory)_failed|session_limit_overflow/iu.test(reason);
106
116
  }
107
117
  /** Every distinct reason behind the gap, sorted, as one spool-ready label. */
@@ -81,7 +81,21 @@ export async function reportCodexSessionAttributions(options) {
81
81
  return emptyCodexSessionReportResult("no_sessions_observed");
82
82
  }
83
83
  const chunks = [];
84
- const sessionChunks = chunkArray(options.sessions, CODEX_SESSION_REPORT_MAX_SESSIONS);
84
+ const sessionChunks = [];
85
+ let current = [];
86
+ let currentBytes = 0;
87
+ for (const session of options.sessions) {
88
+ const bytes = Buffer.byteLength(JSON.stringify(session));
89
+ if (current.length && (current.length >= CODEX_SESSION_REPORT_MAX_SESSIONS || currentBytes + bytes > 3 * 1024 * 1024)) {
90
+ sessionChunks.push(current);
91
+ current = [];
92
+ currentBytes = 0;
93
+ }
94
+ current.push(session);
95
+ currentBytes += bytes;
96
+ }
97
+ if (current.length)
98
+ sessionChunks.push(current);
85
99
  for (const [index, sessions] of sessionChunks.entries()) {
86
100
  const chunk = await postCodexSessionAttributionChunk({
87
101
  ...options,
@@ -253,13 +267,6 @@ export function emptyCodexSessionReportResult(reason) {
253
267
  chunks: [],
254
268
  };
255
269
  }
256
- function chunkArray(items, size) {
257
- const chunks = [];
258
- for (let offset = 0; offset < items.length; offset += size) {
259
- chunks.push(items.slice(offset, offset + size));
260
- }
261
- return chunks;
262
- }
263
270
  /**
264
271
  * How many rows the server must acknowledge, counted per distinct session
265
272
  * rather than per row — the same session observed twice in one chunk is still
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/cli",
3
- "version": "0.2.293",
3
+ "version": "0.2.294",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,9 +27,9 @@
27
27
  "test": "node dist/cli.js --help && node ../../scripts/assert-public-cli-routing.mjs && node ../../scripts/assert-public-cli-verb-help.mjs && node ../../scripts/assert-public-cli-surface-doors.mjs && node ../../scripts/assert-public-cli-runtime-files.mjs && node ../../scripts/assert-public-cli-exit-contract.mjs && node ../../scripts/assert-public-cli-no-fleet-posts.mjs && node ../../scripts/assert-public-cli-doctor-json.mjs && node ../../scripts/assert-public-package-pack.mjs --workspace=@bli-cockpit/cli"
28
28
  },
29
29
  "dependencies": {
30
- "@bli-cockpit/memory-mcp": "0.1.91",
31
- "@bli-cockpit/mcp": "0.1.178",
32
- "@bli-cockpit/telemetry-core": "0.1.97",
30
+ "@bli-cockpit/memory-mcp": "0.1.92",
31
+ "@bli-cockpit/mcp": "0.1.179",
32
+ "@bli-cockpit/telemetry-core": "0.1.98",
33
33
  "unpdf": "1.8.1"
34
34
  },
35
35
  "repository": {